﻿/* $RCSFile: CrmWrapper3.cs $
 * Apache license v2 2011 by Christian Surieux
 * $Source: ?/CRMWrapper3/CrmWrapper3.cs $
 * $log$
 * Revision 6 2010/08/06 19:56:31  christian.surieux
 *   Added Log to All cs files
 */

using System;
using System.ComponentModel;
using System.Security.Principal;
using System.Diagnostics;
using System.Collections;
using System.Collections.Specialized;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Xml.Serialization;
using System.Linq;
using System.Text;
using System.Net;
using System.Web;
using System.Web.Configuration;
using System.Web.Services.Protocols;

using AddonNice.Settings;
using AddonNice.Settings.Cache;
using AddonNice.Security;

using AddonNice.CRMWrapper.CRM3Server;
using AddonNice.CRMWrapper.CRM3Meta;

using CrmSdk.CRM3;

namespace AddonNice.CRMWrapper
{

    public  class Crm3WebService : CrmWebService
    {
        CrmService CrmServ3     =   null;
        #region published properties of CrmService
        public string Url
        {
            get
            {
                return CrmServ3.Url;
            }
            set
            {
				CrmServ3.Url	=	value;
            }
        }
        public bool PreAuthenticate
        {
            get
            {
                return CrmServ3.PreAuthenticate;
            }
            set
            {
				CrmServ3.PreAuthenticate    =	value;
            }
        }
        
        public ICredentials Credentials
        {
            get
            {
                return CrmServ3.Credentials;
            }
            set
            {
				CrmServ3.Credentials    =	value;
            }
        }
        public CallerId CallerIdValue
        {
            get
            {
                return CrmServ3.CallerIdValue;
            }
            set
            {
				CrmServ3.CallerIdValue    =	value;
            }
        }

        #endregion published properties of CrmService

        #region Ctors
        public Crm3WebService(string wurl,bool wpreauth)
        {
            CrmServ3                            =   new CrmService();
            CrmServ3.Url                        =   wurl;
            CrmServ3.PreAuthenticate            =   wpreauth;
        }
        public Crm3WebService(string wurl,bool wpreauth,ICredentials wicred)
        {
            CrmServ3                            =   new CrmService();
            CrmServ3.Url                        =   wurl;
            CrmServ3.PreAuthenticate            =   wpreauth;
            CrmServ3.Credentials                =   wicred;
        }
        public Crm3WebService(string wurl,bool wpreauth,ICredentials wicred,Guid adminUserId)
        {
            CrmServ3                            =   new CrmService();
            CrmServ3.Url                        =   wurl;
            CrmServ3.PreAuthenticate            =   wpreauth;
            CrmServ3.Credentials                =   wicred;
            // we will use the callerId to impersonate on admin account
            CrmServ3.CallerIdValue				=	new CallerId();
            CrmServ3.CallerIdValue.CallerGuid	=	adminUserId;
        }
        #endregion Ctors

        #region published methods of CrmService
        
        public override InternalResponse Execute(InternalRequest req)
        {
            return new InternalResponse(CrmServ3.Execute((Request)req.Content));
        }
        
        public override void Update(InternalBusinessEntity be)
        {
            BusinessEntity e =   (BusinessEntity)be.Content;
            CrmServ3.Update(e);
        }
        public override void Delete(string typename, Guid Id)
        {
            CrmServ3.Delete(typename, Id);
        }
        public override InternalBusinessEntity  Retrieve(string typename, Guid Id,InternalColumnSetBase col)
        {
            return new InternalBusinessEntity(CrmServ3.Retrieve(typename,Id,(ColumnSetBase)col));
        }
        public override InternalBusinessEntityCollection RetrieveMultiple(InternalQueryBase quer)
        {
            return new InternalBusinessEntityCollection(CrmServ3.RetrieveMultiple((QueryBase)quer));
        }
        public override Guid Create(InternalBusinessEntity be)
        {
            BusinessEntity e =   (BusinessEntity)be.Content;
            return CrmServ3.Create(e);
        }
        public override string Fetch(string fetch1)
        {
            return CrmServ3.Fetch(fetch1);
        }

        #endregion published methods of CrmService

        #region Raw methods which work directly with API for internal usage
        
        public Response ExecuteRaw(Request req)
        {
            return CrmServ3.Execute(req);
        }
        
        public void UpdateRaw(BusinessEntity be)
        {
            CrmServ3.Update(be);
        }
        
        public BusinessEntity RetrieveRaw(string typename, Guid Id,ColumnSetBase col)
        {
            return CrmServ3.Retrieve(typename,Id,col);
        }
        
        public BusinessEntityCollection RetrieveMultipleRaw(QueryBase quer)
        {
            return CrmServ3.RetrieveMultiple(quer);
        }
        
        public Guid CreateRaw(BusinessEntity be)
        {
            return CrmServ3.Create(be);
        }

        #endregion Raw methods which work directly with APIU
    }

    public class Crm3MetadataWebService: CrmMetadataWebService
    {
        MetadataService CrmMetaServ3     =   null;

        #region published properties of Crm3MetadataWebService
        public string Url
        {
            get
            {
                return CrmMetaServ3.Url;
            }
            set
            {
				CrmMetaServ3.Url	=	value;
            }
        }
        public bool PreAuthenticate
        {
            get
            {
                return CrmMetaServ3.PreAuthenticate;
            }
            set

            {
				CrmMetaServ3.PreAuthenticate    =	value;
            }
        }
        
        public ICredentials Credentials
        {
            get
            {
                return CrmMetaServ3.Credentials;
            }
            set
            {
				CrmMetaServ3.Credentials    =	value;
            }
        }

        #endregion published properties of Crm3MetadataWebService
        
        
        public Crm3MetadataWebService(string wurl,bool wpreauth,ICredentials wicred)
        {
            CrmMetaServ3                    =   new MetadataService();
            CrmMetaServ3.Url                =   wurl;
            CrmMetaServ3.PreAuthenticate    =   wpreauth;
            CrmMetaServ3.Credentials        =   wicred;
        }

        static public EntityFlags ConvertEntityFlag(EntityInternalItems f)
        {
            EntityFlags fl  = 0;
            if ( ( f & EntityInternalItems.EntityOnly ) == EntityInternalItems.EntityOnly )
                fl |= EntityFlags.EntityOnly;
            if (( f & EntityInternalItems.IncludeAttributes ) == EntityInternalItems.IncludeAttributes )
                fl |= EntityFlags.IncludeAttributes;
            if (( f & EntityInternalItems.IncludePrivileges ) == EntityInternalItems.IncludePrivileges )
                fl |= EntityFlags.IncludePrivileges;
            if (( f & EntityInternalItems.IncludeRelationships ) == EntityInternalItems.IncludeRelationships )
                fl |= EntityFlags.IncludeRelationships;
            if (( f & EntityInternalItems.All ) == EntityInternalItems.All )
                fl |= EntityFlags.All;
            return fl;
        }

        #region published methods of MetadataService

        public override bool ExistEntityMetadata(string entityName)
        {
            EntityMetadata ret   =   CrmMetaServ3.RetrieveEntityMetadata(entityName,EntityFlags.EntityOnly);
            return ( ret.Name == entityName);
        }

        public override EntityInternalMetadata RetrieveEntityMetadata(string entityName, EntityInternalItems f)
        {
            EntityFlags fl  = ConvertEntityFlag(f);
            return new EntityInternalMetadata(CrmMetaServ3.RetrieveEntityMetadata(entityName, fl));
        }

        static public MetadataFlags ConvertMetaDataFlag(EntityInternalItems f)
        {
            MetadataFlags fl  = 0;
            if (( f & EntityInternalItems.EntityOnly ) == EntityInternalItems.EntityOnly )
                fl |= MetadataFlags.EntitiesOnly;
            if (( f & EntityInternalItems.IncludeAttributes ) == EntityInternalItems.IncludeAttributes )
                fl |= MetadataFlags.IncludeAttributes;
            if (( f & EntityInternalItems.IncludePrivileges ) == EntityInternalItems.IncludePrivileges )
                fl |= MetadataFlags.IncludePrivileges;
            if (( f & EntityInternalItems.IncludeRelationships ) == EntityInternalItems.IncludeRelationships )
                fl |= MetadataFlags.IncludeRelationships;
            if (( f & EntityInternalItems.All ) == EntityInternalItems.All )
                fl |= MetadataFlags.All;
            return fl;
        }

        // Object is Metadata
        public override InternalMetadata RetrieveMetadata(EntityInternalItems f)
        {
            MetadataFlags fl  = Crm3MetadataWebService.ConvertMetaDataFlag(f);
            return new InternalMetadata(CrmMetaServ3.RetrieveMetadata(fl));
        }
        public override InternalAttributeMetadata RetrieveAttributeMetadata(string entityName, string attributeName)
        {
            return new InternalAttributeMetadata(CrmMetaServ3.RetrieveAttributeMetadata(entityName, attributeName));
        }
        #endregion published methods of MetadataService

        #region raw methods working directly on API
        
        public EntityMetadata RetrieveEntityMetadataRaw(string entityName, EntityFlags f)
        {
            return CrmMetaServ3.RetrieveEntityMetadata(entityName, f);
        }
        public Metadata RetrieveMetadataRaw(MetadataFlags f)
        {
            return CrmMetaServ3.RetrieveMetadata(f);
        }
        public AttributeMetadata RetrieveAttributeMetadataRaw(string entityName, string attributeName)
        {
            return CrmMetaServ3.RetrieveAttributeMetadata(entityName, attributeName);
        }

        #endregion raw methods working directly on API

    }

    
    public class CrmWrapper3 : CRMWrapperBase
    {
        protected ADNDynSystemUser _adminSysUser            =   null;
        protected ADNDynSystemUser _sysUser                 =   null; // crm user retrieved with WhoAmI Api
        protected ADNDynSystemUser _dbUser2                 =   null; // crm user retrieved from current windows process identity (not current IIS authenticated user)
        protected Guid _userId                              =   Guid.Empty;
        protected Guid _dbUserId                            =   Guid.Empty;
        protected Guid _runningUserId                       =   Guid.Empty;
        protected Guid _adminUserId                         =   Guid.Empty;
        
        protected string _url                               =   string.Empty;
        protected string _urlMeta                           =   string.Empty;
        protected string _urlWebApplication                 =   string.Empty;
        
        protected ICredentials _userCredentials             =   null;
        protected CrmWebService _userService                =   null;

        protected ICredentials _adminCredentials            =   null;
        protected CrmWebService _adminService               =   null;
        protected CrmWebService _adminAdminService          =   null;
        protected  organization _CurrentOrganization        =   null;
        protected bool _impersonateUser                     =   false;
        protected bool _impersonateChecked                  =   false;

        protected string _CRMServiceAccount                 =   Config.CRMServiceAccount; 
        protected string _CRMServicePassword                =   Config.CRMServicePassword; 
        protected string _CRMServiceDomain                  =   Config.CRMServiceDomain;

        /// <summary>
        /// Default eg anonymous CRM account
        /// </summary>
        protected string _CRMServiceDefaultAccount          =   Config.CRMDefaultAccount;
        protected string _CRMServiceDefaultPassword         =   Config.CRMDefaultAccountPassword;
        protected string _CRMServiceDefaultDomain           =   Config.CRMDefaultAccountDomain;

        /// <summary>
        /// PrivateUser Group member
        /// </summary>
        protected string _CRMPrivAccount                    =   Config.CRMPrivAccount;
        protected string _CRMPrivPassword                   =   Config.CRMPrivPassword;
        protected string _CRMPrivDomain                     =   Config.CRMPrivDomain;

        /// <summary>
        /// Admin CRM account
        /// </summary>
        protected override string CRMServiceAccount
        { get{  return _CRMServiceAccount;} set{ _CRMServiceAccount=value;} }
        protected override string CRMServicePassword
        { get{  return _CRMServicePassword;} set{ _CRMServicePassword=value;} }
        protected override string CRMServiceDomain
        { get{  return _CRMServiceDomain;} set{ _CRMServiceDomain=value;} }

        /// <summary>
        /// Default eg anonymous CRM account
        /// </summary>
        protected override string CRMServiceDefaultAccount
        { get{  return _CRMServiceDefaultAccount;} set{ _CRMServiceDefaultAccount=value;} }
        protected override string CRMServiceDefaultPassword
        { get{  return _CRMServiceDefaultPassword;} set{ _CRMServiceDefaultPassword=value;} }
        protected override string CRMServiceDefaultDomain
        { get{  return _CRMServiceDefaultDomain;} set{ _CRMServiceDefaultDomain=value;} }

        /// <summary>
        /// PrivateUser Group member
        /// </summary>
        protected override string CRMPrivAccount
        { get{  return _CRMPrivAccount;} set{ _CRMPrivAccount=value;} }
        protected override string CRMPrivPassword
        { get{  return _CRMPrivPassword;} set{ _CRMPrivPassword=value;} }
        protected override string CRMPrivDomain
        { get{  return _CRMPrivDomain;} set{ _CRMPrivDomain=value;} }

		#region Services objects

        protected ADNAuthenticationType _AuthenticationType =   ADNAuthenticationType.AD; // this is CRM4 authentication type, not asp.net !
        
        public override ADNAuthenticationType AuthenticationType
        {
            get { return _AuthenticationType; }
            set { _AuthenticationType   =   value; }
        }

        protected override CrmWebService userService
        {
            get
            {
                if (_userService == null)
				{
					if ( CRMTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( "[E]CRMWrapperBase _userService null",CRMTraceSwitch.Sw.Info);
					throw new CRMWrapperException("-userService null");
				}
                return _userService;
            }
        }

        protected override CrmWebService adminService
        {
            get
            {
                if ( _adminService == null )
				{
					if ( CRMTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( "[E]CRMWrapperBase _adminService null",CRMTraceSwitch.Sw.Info);
					throw new CRMWrapperException("_adminService null");
				}
                return _adminService;
            }
        }

        protected override CrmWebService adminAdminService
        {
            get
            {
                if (_adminAdminService == null)
				{
					if ( CRMTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( "[E]CRMWrapperBase _adminAdminService null",CRMTraceSwitch.Sw.Info);
					throw new CRMWrapperException("_adminAdminService null");
				}
                return _adminAdminService;
            }
        }

        public override CrmMetadataWebService userMetaService
        {
            get
            {
                if ( _userMetaService == null)
				{
					if ( CRMTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( "[E]CRMWrapperBase _userMetaService null",CRMTraceSwitch.Sw.Info);
					throw new CRMWrapperException("_userMetaService null");
				}
                return _userMetaService;
            }
        }

        public override CrmMetadataWebService adminMetaService
        {
            get
            {
                if ( _adminMetaService == null )
				{
					if ( CRMTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( "[E]CRMWrapperBase _adminMetaService null",CRMTraceSwitch.Sw.Info);
					throw new CRMWrapperException("_adminMetaService null");
				}
                return _adminMetaService;
            }
        }

		#endregion services objects

        Crm3WebService userService3
        {
            get
            {
                return userService as Crm3WebService;
            }
        }

        Crm3WebService adminService3
        {
            get
            {
                return adminService as Crm3WebService;
            }
        }

        Crm3WebService adminAdminService3
        {
            get
            {
                return adminAdminService as Crm3WebService;
            }
        }

        
        Crm3MetadataWebService userMetaService3
        {
            get
            {
                return userMetaService as Crm3MetadataWebService;
            }
        }
        Crm3MetadataWebService adminMetaService3
        {
            get
            {
                return adminMetaService as Crm3MetadataWebService;
            }
        }

        protected CRMUtil3 Util3
        {
            get
            {
                return Util as CRMUtil3;
            }
        }

        protected override string ServiceUrl
        {
            get
            {
                return _url;
            }
            set
            {
                _url    =   value;
            }
        }
        
        protected override string MetaDataServiceUrl
        {
            get
            {
                return _urlMeta;
            }
            set
            {
                _urlMeta    =   value;
            }
        }
        
        protected override string WebApplicationUrl
        {
            get
            {
                return _urlWebApplication;
            }
            set
            {
                _urlWebApplication    =   value;
            }
        }

        public override string DownloadServerUrl
        {
            get
            {
                if (_DownloadServerUrl == string.Empty)
                {
                    string Url2         =   CrmServiceUrl.ToLower();
                    int idx             =   Url2.IndexOf("/mscrmservices");
                    _DownloadServerUrl  =   Url2.Substring(0, idx);
                }
                return _DownloadServerUrl;
            }
        }

        public override string SqlAccessGroupName
        {
            get
            {
                return CurrentOrganization.sqlaccessgroupname;
            }
        }

        public override Guid SqlAccessGroupId
        {
            get
            {
                return CurrentOrganization.sqlaccessgroupid.Value;
            }
        }

        public override string ReportingGroupName
        {
            get
            {
                return CurrentOrganization.reportinggroupname;
            }
        }

        public override Guid ReportingGroupID
        {
            get
            {
                return CurrentOrganization.reportinggroupid.Value;
            }
        }

        public override Guid UserGroupId
        {
            get
            {
                return CurrentOrganization.usergroupid.Value;
            }
        }

        public override string CurrencySymbol
        {
            get
            {
                return CurrentOrganization.currencysymbol;
            }
        }

        public override Guid BaseCurrencyId 
        {
            get
            {
                return Guid.Empty;
            }
        }

        public override int LanguageCode
        {
            get
            {
                return CurrentOrganization.languagecode.Value;
            }
        }

        public organization CurrentOrganization
        {
            get
            {
                return _CurrentOrganization;
            }
            set
            {
                if ( value == null )
                    return;
                _CurrentOrganization        =   value;
                _SchemaNamePrefix           =   value.schemanameprefix;
                _FullNameFormat             =   value.fullnameconventioncode.Value;
                _FullNameFormatName         =   value.fullnameconventioncode.name;
                OrganizationId              =   value.organizationid.Value;
                OrganizationName            =   value.name;
                OrganizationFriendlyName    =   value.name;
            }
        }
            


        public CrmWrapper3(string wurl,string CRMServiceAccount,string CRMServicePassword,string CRMServiceDomain,
            string CRMDefaultAccount,string CRMDefaultAccountPwd,string CRMDefaultAccountDn, 
            string CRMPrivAccount,string CRMPrivPassword,string CRMPrivDomain)
                : base(wurl,CRMServiceAccount,CRMServicePassword,CRMServiceDomain,
                    CRMDefaultAccount, CRMDefaultAccountPwd, CRMDefaultAccountDn, 
                    CRMPrivAccount,CRMPrivPassword,CRMPrivDomain)
        {
            //AddonNice.CRMWrapper.Properties.Settings.Default["CRMWrapper_CRM3Server_CrmService"] = wurl;
            // initialize the utilities extension
            Util            =       new CRMUtil3(this);
            // Create the admin services
            InitAdminService(Config.CRMUsePreAuthenticate);
            // Dispatch a Constructed event to all requesting objects
            CrmWrapperEventArgs ev  =   new CrmWrapperEventArgs(this,wrapperEventType.Constructed);
            OnCrmWrapperEvent(ev);
        }

		/// <summary>
		/// Current user name
		/// </summary>
        public override string userName
        {
            get
            {
                if ( _sysUser != null)
                    return _sysUser.domainname;
                return string.Empty;
            }
        }

		/// <summary>
        /// BusinessUnit of current user
        /// </summary>
		public override Guid businessUnitId
        {
            get
            {
                if ( _sysUser != null )
                    return _sysUser.businessunitid;
                return Guid.Empty;
            }
        }

		/// <summary>
		/// Flag to avoid several impersonation checking
		/// </summary>
        public bool impersonateChecked     
        {
            get
            {
                return _impersonateChecked;
            }
        }

		/// <summary>
        /// When we  call this method from an iFrame, the identity may be different from logged user
        /// then we need to impersonate to logged user
        /// this property is the corresponding indicator 
		/// </summary>
        protected bool impersonateUser
        {
            get
            {
                if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 impersonateUser _impersonateChecked: {0}", _impersonateChecked),CRMTraceSwitch.Sw.Info);
                if (_impersonateChecked)
                    return _impersonateUser;
                // retrieve a systemUser entity from context windows logon identity
                GetCurrentUser();
                // retrieve the userId from whoAmI API, calling it normally by the userService which uses CredentialCache in Windows authentication mode
                // this could be different in the case we are under an iFrame in CRM: it appeared that CRM iFrame are runned under NETWORK_SERVICE account
                try
                {
                    GetUser();
                }
                catch ( Exception ex )
                {
                    if ( CRMTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 impersonateUser GetUser ex: {0}.", ex),CRMTraceSwitch.Sw.Info);
                }
                // if the logged user is not identical to user corresponding to the running identity process, we need to impersonate to have the real user calling the CRM
                // in this case the _dbUSer2 is the entity that need to act as the real user
                // so we do the swap
                if (_dbUserId  != Guid.Empty &&  _dbUserId != _userId)
                {
                    if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 impersonateUser _dbUserId: {0} != _userId {1}", _dbUserId, _userId),CRMTraceSwitch.Sw.Info);
                    _runningUserId              =   _userId;
                    userId						=   _dbUserId;
                    sysUser						=   _dbUser2;
                    _impersonateUser            =   true;
                }
                _impersonateChecked             =   true;
                if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 impersonateUser : {0}", _impersonateUser),CRMTraceSwitch.Sw.Info);
                // Dispatch a SysUserSet event to all requesting objects
                CrmWrapperEventArgs ev          =   new CrmWrapperEventArgs(this,wrapperEventType.SysUserSet);
                OnCrmWrapperEvent(ev);
                return _impersonateUser;
            }
        }

        /// <summary>
        /// SystemUser corresponding to the authentified user
		/// </summary>
        ADNDynSystemUser sysUser
        {
            get
            {
                if (_sysUser == null)
                    GetUser();
                return _sysUser;
            }
			set
			{
                _sysUser	=	value;
				// we should have a dynamic typeCode here
                if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 sysUser set fullname: {0}", _sysUser.fullname),CRMTraceSwitch.Sw.Info);
			}
        }

		/// <summary>
		/// The Guid corresponding to the authentified user, obtained with whoAmI using userService
		/// </summary>
        public override Guid userId
        {
            get
            {
                if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 userId begin _userId == Guid.Empty : '{0}'", _userId == Guid.Empty),CRMTraceSwitch.Sw.Info);
                if (_userId == Guid.Empty)
                {
                    try
                    {
                        WhoAmIRequest request1		= new WhoAmIRequest();
                        WhoAmIResponse response1	= (WhoAmIResponse)userService3.ExecuteRaw(request1);
                        _userId						= response1.UserId;
						// we should have a dynamic typeCode here
                        if ( CRMTraceSwitch.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 userId WhoAmI Ok _userId : '{0}'", _userId),CRMTraceSwitch.Sw.Info);
                    }
                    catch (SoapException sx)
                    {
                        if ( CRMTraceSwitch.Sw.TraceError )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 userId.get ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
                        throw new CRMWrapperException("Get UserId soap: "+sx.Detail.InnerText, sx);
                    }
                    catch (CRMWrapperException )
                    {
                        throw;
                    }
                    catch (Exception ex)
                    {
                        if ( CRMTraceSwitch.Sw.TraceError )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 userId.get ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                        throw new CRMWrapperException("Get UserId ex", ex);
                    }
                }
                return _userId;
            }
			set
			{
				_userId						= value;
				// we should have a dynamic typeCode here
                if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 userId set: {0}", _userId),CRMTraceSwitch.Sw.Info);
			}
        }

        
        
        /// <summary>
        /// Get the systemuser entity from the userid by calling RetrieveSystemUser API
        /// Set it in _SysUser, 
        /// </summary>
        ADNDynSystemUser GetUser()
        {
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetUser BEG _sysUser != null: {0}", _sysUser != null),CRMTraceSwitch.Sw.Info);
            if ( _sysUser != null )
                return _sysUser;
            try
            {
                ADNDynSystemUser sUser              =   new ADNDynSystemUser(this,userId);
                if ( sUser.adminRetrieve() )
                {
                    sysUser							=   sUser;
                    if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetUser END _sysUser.domainname: {0}-{1}", _sysUser.domainname,_sysUser.fullname),CRMTraceSwitch.Sw.Info);
					return _sysUser;
				}
            }
            catch (SoapException sx)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetUser ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException("GetUser soap: " + sx.Detail.InnerText, sx);
            }
            catch (CRMWrapperException)
            {
                throw;
            }
            catch (Exception ex)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetUser ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException("GetUser ex", ex);
            }
            const string msgex  =   "[E]CRMWrapper3 GetUser failed.";
            if ( CRMTraceSwitch.Sw.TraceError )
                Trace.WriteLine(msgex,CRMTraceSwitch.Sw.Info);
			throw new CRMWrapperException(msgex);
        }

        /// <summary>
        /// Get the systemUser entity from the Context Identity by calling the CRM database systemusers with this key
        /// set it in _dbUser2 and _dbUserId 
        /// </summary>
        ADNDynSystemUser GetCurrentUser()
        {
            if (_dbUser2 != null)
                return _dbUser2;
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetCurrentUser BEG HttpContext.Current not null: {0}", HttpContext.Current!= null ),CRMTraceSwitch.Sw.Info);
            string CrmName			            =   string.Empty;
			Guid uId				            =	Guid.Empty; 
            // if request authenticated, try to get name from IIdentity
			// beware that Request.IsAuthenticated could be false and Request.LogonUserIdentity.IsAuthenticated true, 
            // because we are called from Windows_OnAuthenticate in global.asax
			IIdentity wid		                =   null;
            if ( SecurityTraceSwitch.Sw.TraceVerbose || AuthenticationTrace.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetCurrentUser Config.AuthenticationMode: {0}, Request.IsAuthenticated: {1}.", Config.AuthenticationMode,HttpContext.Current.Request.IsAuthenticated), 
                    (SecurityTraceSwitch.Sw.TraceVerbose ) ? SecurityTraceSwitch.Sw.Info:AuthenticationTrace.Sw.Info);
			if ( HttpContext.Current.Request.IsAuthenticated )
			{
			    if ( Config.AuthenticationMode == AuthenticationMode.Forms )
			    {
				    wid				            =	HttpContext.Current.User.Identity;
				    CrmName			            =	wid.Name;
				    if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetCurrentUser CrmName set from HttpContext.Current.User.Identity: {0}, CrmName: {1}", HttpContext.Current.User.Identity, HttpContext.Current.User.Identity.Name),CRMTraceSwitch.Sw.Info);
				    // we try to get a Crm userId from Identity, beware that it could be Guid.Empty
				    if (wid is AddonNiceIdentity)
				    {
                        AddonNiceIdentity Aid   =   (AddonNiceIdentity)wid;
					    uId			            =   Aid.CrmImpersonateId;
                        // real CRM name is not user name 
				        CrmName			        =	string.Format("{0}\\{1}",Aid.CrmImpersonateDomain,Aid.CrmImpersonateLogin);
					    if ( CRMTraceSwitch.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetCurrentUser get userId from IIdentity: {0}", uId),CRMTraceSwitch.Sw.Info);
				    }
                }
			    else if ( Config.AuthenticationMode == AuthenticationMode.Windows ) 
			    {
                    bool isADNPrinc             =   (HttpContext.Current.User is ADNCRMPrincipal);

                    if (CRMTraceSwitch.Sw.TraceVerbose)
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetCurrentUser AuthenticationMode.Windows: Current.User is ADNCRMPrincipal: {0}.",isADNPrinc), CRMTraceSwitch.Sw.Info);
                    // Update Identity with CRM ids for user
                    if (isADNPrinc)
                    {
                        try
                        {
                            Guid wUserId        =   userId;
                            if ( SecurityTraceSwitch.Sw.TraceVerbose || AuthenticationTrace.Sw.TraceVerbose )
                                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetCurrentUser setting AdonniceIdentity CrmId : {0}", wUserId),
                                                (SecurityTraceSwitch.Sw.TraceVerbose ) ? SecurityTraceSwitch.Sw.Info:AuthenticationTrace.Sw.Info);
                            ((ADNCRMPrincipal)HttpContext.Current.User).AddonNiceIdentity.SetCrmId(wUserId, (int)ADNTypeCodes.SystemUser);
                        }
                        catch (SoapException sx) // Not fatal here userId could not be retrieved -> pb HTTP 401
                        {
                            if ( CRMTraceSwitch.Sw.TraceError )
                                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetCurrentUser SetCrmId ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
                        }
                        catch (Exception ex) // Not fatal here
                        {
                            if ( CRMTraceSwitch.Sw.TraceError )
                                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetCurrentUser SetCrmId ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                        }
                    }
                    //CrmName                     =   HttpContext.Current.Request.LogonUserIdentity.Name; -> pb sous IIS7.5 NETWORK_SERVICES ????
                    CrmName                     =   HttpContext.Current.User.Identity.Name;
                    if (CRMTraceSwitch.Sw.TraceVerbose)
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetCurrentUser CrmName set from LogonUserIdentity.Name: {0}", CrmName), CRMTraceSwitch.Sw.Info);
			    }
			}
			// if we get a valid Id, get user from this Id
			if ( uId != Guid.Empty )
			{
				_dbUser2				        =   GetUserById2(uId);
				if (_dbUser2 != null)
				{
					_dbUserId		            =   _dbUser2.systemuserid;
					if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetCurrentUser END Ok from userId: {0}, CrmName: {1}", uId,_dbUser2.domainname),CRMTraceSwitch.Sw.Info);
					return _dbUser2;
				}
			}
			// if CrmName still empty, take the default account
			if ((Config.AuthenticationMode == AuthenticationMode.Forms) && string.IsNullOrEmpty(CrmName))
			{
				CrmName                         =   string.Format("{0}\\{1}",Config.CRMDefaultAccountDomain,Config.CRMDefaultAccount);
				if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetCurrentUser taking default identity to retrieve user CrmName: {0}", CrmName),CRMTraceSwitch.Sw.Info);
			}
			if (!string.IsNullOrEmpty(CrmName))
			{
				_dbUser2                        =   GetUserByDomainName2(CrmName);
				if (_dbUser2 != null)
				{
					_dbUserId                   =   _dbUser2.systemuserid;
					if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetCurrentUser END Ok with domainName: dbUser2.domainname: {0}, CrmName : {1}, dbUserId: {2}", 
                            new object[] { _dbUser2.domainname, CrmName, _dbUserId }),CRMTraceSwitch.Sw.Info);
					return _dbUser2;
				}
			}
            const string msgex                  =   "[E]CRMWrapper3 GetCurrentUser null.";
			if ( CRMTraceSwitch.Sw.TraceError )
                Trace.WriteLine( msgex,CRMTraceSwitch.Sw.Info);
			return null;
			// we should have a user here so don't allow to continue
			//throw new CRMWrapperException(msgex);
        }

        /// <summary>
        /// Domain name for the admin account
        /// </summary>
        public override string adminUserName
        {
            get
            {
                if (_adminSysUser != null)
                    return _adminSysUser.domainname;
                return string.Empty;
            }
        }

        protected ADNDynSystemUser InitAdminUser()
        {
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 InitAdminUser BEG _adminSysUser != null : {0}",_adminSysUser != null),CRMTraceSwitch.Sw.Info);
            if ( _adminSysUser != null)
                return _adminSysUser;
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 InitAdminUser _adminUserId: {0}",_adminUserId),CRMTraceSwitch.Sw.Info);
            try
            {
                ADNDynSystemUser sUser              =   new ADNDynSystemUser(this,_adminUserId);
                if ( sUser.adminRetrieve() )
                {
                    _adminSysUser                   =   sUser; 
                    if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 InitAdminUser _adminUserId: {0}, _adminSysUser.domainname: {1}",
                                _adminUserId,_adminSysUser.domainname),CRMTraceSwitch.Sw.Info);
                }
                /*
                TargetRetrieveSystemUser target		=   new TargetRetrieveSystemUser();
                target.EntityId						=   _adminUserId;
                RetrieveRequest req					=   new RetrieveRequest();
                req.ColumnSet						=   new AllColumns();
                req.Target							=   target;
                req.ReturnDynamicEntities			=   false;
                RetrieveResponse r				    =   (RetrieveResponse)adminAdminService3.ExecuteRaw(req);
                if (r != null)
                {
                    _adminSysUser					= ( systemuser)r.BusinessEntity;
                    if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 InitAdminUser _adminUserId: {0}, _adminSysUser.domainname: {1}",
                                _adminUserId,_adminSysUser.domainname),CRMTraceSwitch.Sw.Info);
                }
                 */
            }
            catch (SoapException sx)
            {
                string msg  =   string.Format("[E]CRMWrapper3 InitAdminUser ex: {0}-{1}", sx, sx.Detail.InnerText);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException(msg, sx);
            }
            catch (CRMWrapperException)
            {
                throw;
            }
            catch (Exception ex)
            {
                string msg  =   string.Format("[E]CRMWrapper3 InitAdminUser ex: {0}", ex);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException("InitAdminUser ex", ex);
            }
            finally
            {
                //adminService3.Credentials       =   savcred;
            }
            return _adminSysUser;
        }

		/// <summary>
		/// Guid of CRM administrator specified in config file
		/// </summary>
        public override Guid adminUserId
        {
            get
            {
                if ( _adminUserId == Guid.Empty )
                {
                    try
                    {
                        WhoAmIRequest request1      =   new WhoAmIRequest();
                        WhoAmIResponse response1    =   (WhoAmIResponse)adminAdminService3.ExecuteRaw(request1);
                        _adminUserId                =   response1.UserId;
                        if ( CRMTraceSwitch.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 adminUserId GET WhoAmI _adminUserId : '{0}'", _adminUserId),CRMTraceSwitch.Sw.Info);
                        InitAdminUser();
                        if ( CRMTraceSwitch.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 adminUserId.get WhoAmI AdminUserName : {0}, _adminUserId : '{1}'", adminUserName, _adminUserId),CRMTraceSwitch.Sw.Info);
                    }
                    catch (SoapException sx)
                    {
                        if ( CRMTraceSwitch.Sw.TraceError )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 adminUserId.get ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
                        throw new CRMWrapperException("adminUserId soap: "+sx.Detail.InnerText, sx);
                    }
                    catch (CRMWrapperException)
                    {
                        throw;
                    }
                    catch (Exception ex)
                    {
                        if ( CRMTraceSwitch.Sw.TraceError )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 adminUserId ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                        throw new CRMWrapperException("adminUserId ex", ex);
                    }
                }
                return _adminUserId;
            }
        }
   
        /// <summary>
        /// Sent by WrapperBase just after InitServices completion to get information about actual organisation admin settings
        /// </summary>
        protected override void ReadCurrentOrganization()
        {
            try
            {
                const string ckey					=   "CRM_CurrentOganization";
                if ( CurrentCache.Exists(ckey))
                {
                    CurrentOrganization		        =  (organization)CurrentCache.Get(ckey);
                    if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 ReadCurrentOrganization found in cache _CurrentOrganization: {0}, languagecode: {1}", _CurrentOrganization.name,_CurrentOrganization.languagecode.Value),CRMTraceSwitch.Sw.Info);
                    return;
                }
                
                
                // Where id the Id ??? TargetRetrieveOrganization target   =   new TargetRetrieveOrganization();
                // must use a RetrieveMultiple and take the first....which should be the only one
                RetrieveMultipleRequest req         =   new RetrieveMultipleRequest();
                
                QueryExpression query               =   new QueryExpression();
                query.ColumnSet                     =   new AllColumns();
                query.EntityName                    =   CrmStr.organization;
                req.Query                           =   query;     
                RetrieveMultipleResponse r          =  (RetrieveMultipleResponse)adminAdminService3.ExecuteRaw(req);
                if (r != null && r.BusinessEntityCollection.BusinessEntities[0] != null )
                {
                    CurrentOrganization		     = (organization)r.BusinessEntityCollection.BusinessEntities[0];
                    CurrentCache.Insert(ckey,CurrentOrganization);

                    if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 ReadCurrentOrganization _CurrentOrganization: {0}, languagecode: {1}", _CurrentOrganization.name,_CurrentOrganization.languagecode.Value),CRMTraceSwitch.Sw.Info);
					return;
				}
            }
            catch (SoapException sx)
            {
                string msg  =   string.Format("[E]CRMWrapper3 ReadCurrentOrganization ex: {0}-{1}", sx, sx.Detail.InnerText);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException(msg, sx);
            }
            catch (CRMWrapperException)
            {
                throw;
            }
            catch (Exception ex)
            {
                string msg  =   string.Format("[E]CRMWrapper3 ReadCurrentOrganization ex: {0}", ex);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException(msg, ex);
            }
            const string msg0  =   "[E]CRMWrapper3  ReadCurrentOrganization failed throwing Exception";
            if ( CRMTraceSwitch.Sw.TraceError )
                Trace.WriteLine(msg0,CRMTraceSwitch.Sw.Info);
            throw new CRMWrapperException(msg0);
        }

        public override bool IsUserOk4Crm(string domain,string login,string pwd)
        {
			if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( "[V]CRMWrapper3 IsUserOk4Crm BEG.",CRMTraceSwitch.Sw.Info);
            bool ret                            =   false;
            try
            {
                WhoAmIRequest request1		=   new WhoAmIRequest();
                switch ( AuthenticationType )
                {
                    case ADNAuthenticationType.AD:
                    NetworkCredential cred      =   new NetworkCredential(login,pwd,domain);
                    Crm3WebService TestService	=	new Crm3WebService(_url,false,cred);
				    if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 IsUserCredentialsOk Service Ok url: {0}",_url),CRMTraceSwitch.Sw.Info);
                    TestService.ExecuteRaw(request1);
                    ret                         =   true;
                     break;
                    case ADNAuthenticationType.SPLA:
                    case ADNAuthenticationType.Online:
                    break;
                }
            }
            catch (Exception ex)
            {
                string msg  =   string.Format("[E]CRMWrapper3 IsUserOk4Crm ex: {0}.", ex);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
            }
			if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 IsUserOk4Crm END: {0}",ret),CRMTraceSwitch.Sw.Info);
            return ret;       
        }

        /// <summary>
		/// Credentials used for the userService in AD mode
		/// If Addon Nice authentication mode is windows, it default to the windows user credential set in CredentialCache
		/// If Addon Nice authentication mode is forms, depends on:
		/// - if user authenticated, new credentials will be created from the current authenticated user, see AddonNiceIdentity
		/// - if not authenticated (anonymous), new credentials will be used from default crm user set in web.config
		/// </summary>
        public ICredentials userCredentials
        {
            get
            {
                if (_userCredentials == null)
                {
                    if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( "[V]CRMWrapperBase userCredentials GET BEG.",CRMTraceSwitch.Sw.Info);
                    try
                    {
						AuthenticationMode auth	        =	Config.AuthenticationMode;
						if ( CRMTraceSwitch.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapperBase userCredentials authenticationMode: {0}", auth),CRMTraceSwitch.Sw.Info);
						if ( auth == AuthenticationMode.Windows )
						{
			                if ( CRMTraceSwitch.Sw.TraceVerbose )
                                Trace.WriteLine( "[V]CRMWrapperBase userCredentials Windows Mode, using CredentialCache.",CRMTraceSwitch.Sw.Info);
							_userCredentials            =   System.Net.CredentialCache.DefaultCredentials;
						}
                        // Authentication == Forms
                        if (auth == AuthenticationMode.Forms)
                        {
                            if (HttpContext.Current.Request.IsAuthenticated 
                                && ( HttpContext.Current.User.Identity is AddonNiceIdentity ))// <- when in first setup we could have a FormIdentity
                            {
			                    if ( CRMTraceSwitch.Sw.TraceVerbose )
                                    Trace.WriteLine( "[V]CRMWrapperBase userCredentials Forms Mode, IsAuthenticated true.",CRMTraceSwitch.Sw.Info);
                                AddonNiceIdentity AId   =   (AddonNiceIdentity)HttpContext.Current.User.Identity;
                                _userCredentials        =   AId.Credentials;
                            }
                            else // If we are in Forms authentication with non authenticated user, we need some default account to logon
                            {
                                if ( CRMTraceSwitch.Sw.TraceVerbose )
                                    Trace.WriteLine(
                                    string.Format("[V]CRMWrapperBase userCredentials Forms Mode not authenticated getting credentials from default values to allow logon: {0}-{1}-{2}.", Config.CRMDefaultAccount,
                                        CRMServiceDefaultAccount,CRMServiceDefaultPassword,CRMServiceDefaultDomain),CRMTraceSwitch.Sw.Info);
                                // if not authenticated use default values
                                _userCredentials        =   new NetworkCredential(CRMServiceDefaultAccount,CRMServiceDefaultPassword,CRMServiceDefaultDomain);
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        if ( CRMTraceSwitch.Sw.TraceError )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapperBase userCredentials ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                        throw new CRMWrapperException("CRMWrapperBase userCredentials ex", ex);
                    }
                }
                if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( "[V]CRMWrapperBase userCredentials END.",CRMTraceSwitch.Sw.Info);
                return _userCredentials;
            }
         }

        /// <summary>
        /// Credentials for the CRM administrator specified in config file: new NetworkCredential 
        /// </summary>
		public ICredentials adminCredentials
        {
            get
            {
                if (_adminCredentials == null)
                {
                    try
                    {
                        if ( CRMTraceSwitch.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 adminCredentials Account : {0}, Pwd :{1}, Domain :{2}", CRMServiceAccount,CRMServicePassword,CRMServiceDomain),CRMTraceSwitch.Sw.Info);
                        _adminCredentials =     new NetworkCredential(CRMServiceAccount,CRMServicePassword,CRMServiceDomain);
                    }
                    catch (Exception ex)
                    {
                        if ( CRMTraceSwitch.Sw.TraceError )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 adminCredentials ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                        throw new CRMWrapperException("adminCredentials ex", ex);
                    }
                }

                return _adminCredentials;
            }
        }

        protected override void InitAdminService(bool UsePreAuthenticate)
        {
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( "[V]CRMWrapper3 InitAdminService BEG.",CRMTraceSwitch.Sw.Info);
            if (_adminAdminService == null)
            {
				if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( "[V]CRMWrapper3 InitAdminService adminAdminService start.",CRMTraceSwitch.Sw.Info);
                try
                {
                    // Cache credentials so we don't have to re-authenticate on each request.
                    _adminAdminService						=	new Crm3WebService(_url,UsePreAuthenticate,adminCredentials);
					if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 InitAdminService _adminAdminService Ok url: {0}",_url),CRMTraceSwitch.Sw.Info);
                }
                catch (SoapException sx)
                {
                    if ( CRMTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 InitAdminService adminAdminService sx : {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
                    throw new CRMWrapperException("adminAdminService soap: " + sx.Detail.InnerText, sx);
                }
                catch (CRMWrapperException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    if ( CRMTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 InitAdminService adminAdminService ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                    throw new CRMWrapperException("adminAdminService ex", ex);
                }
				if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( "[V]CRMWrapper3 InitAdminService adminAdminService end",CRMTraceSwitch.Sw.Info);
            }
            if (_adminService == null)
            {
				if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( "[V]CRMWrapper3 InitAdminService _adminService start",CRMTraceSwitch.Sw.Info);
                try
                {
                    // install credential after this because userCredential uses AdminService
                    //_adminService							=	new Crm3WebService(_url,true,userCredentials,adminUserId);
                    _adminService							=	_adminAdminService;
                    if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 InitAdminService _adminService.CallerIdValue : {0}", adminUserId),CRMTraceSwitch.Sw.Info);
                }
                catch (SoapException sx)
                {
                    if ( CRMTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 InitAdminService adminService sx : {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
                    throw new CRMWrapperException("adminService soap: " + sx.Detail.InnerText, sx);
                }
                catch (CRMWrapperException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    if ( CRMTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 InitAdminService adminService ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                    throw new CRMWrapperException("adminService ex", ex);
                }
				if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( "[V]CRMWrapper3 InitAdminService _adminService end",CRMTraceSwitch.Sw.Info);
            }
			if ( _adminMetaService == null )
            {
				if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( "[V]CRMWrapper3 InitAdminService _adminMetaService start",CRMTraceSwitch.Sw.Info);
                try
                {
                    _adminMetaService						=	new Crm3MetadataWebService(_urlMeta,true,adminCredentials);
                    if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( "[V]CRMWrapper3 InitAdminService _adminMetaService Ok",CRMTraceSwitch.Sw.Info);
                }
                catch (SoapException sx)
                {
                    if ( CRMTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 InitAdminService _adminMetaService sx : {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
                    throw new CRMWrapperException("adminMetaService soap: " + sx.Detail.InnerText, sx);
                }
                catch (CRMWrapperException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    if ( CRMTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 InitAdminService _adminMetaService ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                    throw new CRMWrapperException("adminMetaService ex", ex);
                }
				if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( "[V]CRMWrapper3 InitAdminService _adminMetaService end",CRMTraceSwitch.Sw.Info);
            }

            _isAdminInitialized      =   true;
            // We need this to call wrapper only after Application_AuthenticateRequest ahs run
            // if Application_AuthenticateRequest is not runned we can get the Http.Context.Current.User and never reach this point
             if ( CRMTraceSwitch.Sw.TraceVerbose )
                 Trace.WriteLine( "[V]CRMWrapper3 InitAdminService END Ok",CRMTraceSwitch.Sw.Info);
        }

        protected override void InitServices(bool UsePreAuthenticate)
        {
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( "[V]CRMWrapper3 InitServices BEG.",CRMTraceSwitch.Sw.Info);
            if (_userService == null)
            {
				if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( "[V]CRMWrapper3 InitServices _userService start",CRMTraceSwitch.Sw.Info);
                try
                {
                    // Cache credentials so we don't have to re-authenticate on each request.
                    _userService							=	new Crm3WebService(_url,UsePreAuthenticate,userCredentials);
					if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 InitServices _userService Ok url: {0}",_url),CRMTraceSwitch.Sw.Info);
                }
                catch (SoapException sx)
                {
                    if ( CRMTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 InitServices userService ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
                    throw new CRMWrapperException("userService soap: " + sx.Detail.InnerText, sx);
                }
                catch (CRMWrapperException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    if ( CRMTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 InitServices userService ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                    throw new CRMWrapperException("userService ex", ex);
                }
				if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( "[V]CRMWrapper3 InitServices _userService end",CRMTraceSwitch.Sw.Info);
            }
			if (_userMetaService == null)
			{
				if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( "[V]CRMWrapper3 InitServices _userMetaService start",CRMTraceSwitch.Sw.Info);
				try
				{
					// Cache credentials so we don't have to re-authenticate on each request.
					_userMetaService						=	new Crm3MetadataWebService(_urlMeta,UsePreAuthenticate,userCredentials);
					if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 InitServices _userMetaService Ok url: {0}",_urlMeta),CRMTraceSwitch.Sw.Info);
				}
				catch (SoapException sx)
				{
					if ( CRMTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 InitServices _userMetaService sx : {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
					throw new CRMWrapperException("userMetaService soap: " + sx.Detail.InnerText, sx);
				}
				catch (CRMWrapperException)
				{
					throw;
				}
				catch (Exception ex)
				{
					if ( CRMTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 InitServices _userMetaService ex: {0}", ex),CRMTraceSwitch.Sw.Info);
					throw new CRMWrapperException("userMetaService ex", ex);
				}
				if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( "[V]CRMWrapper3 InitServices _userMetaService end",CRMTraceSwitch.Sw.Info);
			}
            try
            {
				if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( "[V]CRMWrapper3 InitServices impersonate test start",CRMTraceSwitch.Sw.Info);
                if (impersonateUser)
                {
					if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( "[V]CRMWrapper3 InitServices impersonate true",CRMTraceSwitch.Sw.Info);
                    userService3.CallerIdValue	            =   new CallerId();
                    userService3.CallerIdValue.CallerGuid	=   userId;
                }
                if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 InitServices impersonateUser: {0}, userId: {1}, userName:{2}", impersonateUser, _userId, userName),CRMTraceSwitch.Sw.Info);
            }
            catch (SoapException sx)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 InitServices ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException("userService soap: " + sx.Detail.InnerText, sx);
            }
            catch (CRMWrapperException)
            {
                throw;
            }
            catch (Exception ex)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 InitServices ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException("userService ex", ex);
            }

            _isInitialized      =   true;
            // We need this to call wrapper only after Application_AuthenticateRequest ahs run
            // if Application_AuthenticateRequest is not runned we can get the Http.Context.Current.User and never reach this point
             if ( CRMTraceSwitch.Sw.TraceVerbose )
                 Trace.WriteLine( "[V]CRMWrapper3 InitServices END Ok",CRMTraceSwitch.Sw.Info);
        }

        #region Create compound operations

        public override Guid userCreateCompound(InternalTargetCompound target)
        {
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 userCreateCompound TargetCompound Type: {0}", target),CRMTraceSwitch.Sw.Info);
            CompoundCreateRequest createReq =   new CompoundCreateRequest();
            createReq.Target                =   (TargetCompound)target.Content;
            CompoundCreateResponse cr       =   (CompoundCreateResponse)CreateRaw(createReq,false);
            return cr.Id;
        }

        /// <summary>
        public override Guid userCreateCompound(DynEntity entity,List<DynEntity> childs)
        {
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 userCreateCompound TargetCompound entity: {0}",entity.SchemaName),CRMTraceSwitch.Sw.Info);
            CompoundCreateRequest createReq =   new CompoundCreateRequest();
            createReq.Target                =   MakeTargetCompoundDynamicRaw(entity,childs);
            CompoundCreateResponse cr       =   (CompoundCreateResponse)CreateRaw(createReq,false);
            return cr.Id;
        }

        /// Create compound entity dynamic or not with the admin account
        /// To create Dynamic use a TargetCoumpounDynamic
        /// </summary>
        public override Guid adminCreateCompound(InternalTargetCompound target)
        {
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 adminCreateCompound TargetCompound Type: {0}", target),CRMTraceSwitch.Sw.Info);
            CompoundCreateRequest createReq =   new CompoundCreateRequest();
            createReq.Target                =   (TargetCompound)target.Content;
            CompoundCreateResponse cr       =   (CompoundCreateResponse)CreateRaw(createReq,true);
            return cr.Id;
        }

        /// <summary>
        /// Dynamic create compound entity with the admin account
        /// </summary>
        public override Guid adminCreateCompound(DynEntity entity,List<DynEntity> childs)
        {
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 adminCreateCompound TargetCompound entity: {0}", entity.SchemaName),CRMTraceSwitch.Sw.Info);
            CompoundCreateRequest createReq =   new CompoundCreateRequest();
            createReq.Target                =   MakeTargetCompoundDynamicRaw(entity,childs);
            CompoundCreateResponse cr       =   (CompoundCreateResponse)CreateRaw(createReq,true);
            return cr.Id;
        }

        #endregion Create compound operations

        #region Rollup operations

        public override InternalResponse userRollup(string entityNm,Guid Id,InternalQueryBase quer,bool isDynamic)
        {
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 userRollup entity: {0}, Id: {1}, isDynamic: {2}", entityNm,Id,isDynamic),CRMTraceSwitch.Sw.Info);
            RollupResponse bu     =   RollupRaw(entityNm,Id,(QueryBase)quer,isDynamic,false);
            return new InternalResponse(bu);
        }

        public override InternalResponse userRollup(DynEntity entity,InternalQueryBase quer)
        {
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 userRollup dynEntity: {0}, Id: {1}", entity.SchemaName,entity.PrimaryKeyGuidValue),CRMTraceSwitch.Sw.Info);
            RollupResponse bu     =   RollupRaw(entity.SchemaName,entity.PrimaryKeyGuidValue,(QueryBase)quer,true,false);
            return new InternalResponse(bu);
        }

        /// <summary>
        /// Dynamic create compound entity with the admin account
        /// </summary>
        public override InternalResponse adminRollup(string entityNm,Guid Id,InternalQueryBase quer,bool isDynamic)
        {
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 adminRollup entity: {0}, Id: {1}, isDynamic: {2}", entityNm,Id,isDynamic),CRMTraceSwitch.Sw.Info);
            RollupResponse bu     =   RollupRaw(entityNm,Id,(QueryBase)quer,isDynamic,true);
            return new InternalResponse(bu);
        }

        /// <summary>
        /// Dynamic create compound entity with the admin account
        /// </summary>
        public override InternalResponse adminRollup(DynEntity entity,InternalQueryBase quer)
        {
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 adminRollup dynEntity: {0}, Id: {1}", entity.SchemaName,entity.PrimaryKeyGuidValue),CRMTraceSwitch.Sw.Info);
            RollupResponse bu     =   RollupRaw(entity.SchemaName,entity.PrimaryKeyGuidValue,(QueryBase)quer,true,true);
            return new InternalResponse(bu);
        }

        public RollupResponse RollupRaw(string entityNm,Guid Id,QueryBase quer,bool isDynamic, bool admin)
        {
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 RollupRaw BEG entity: {0}, Id: {1}, isDynamic: {2}", entityNm,Id,isDynamic),CRMTraceSwitch.Sw.Info);

            RollupResponse rr               =   null;

            try
            {
                RollupRequest req               =   new RollupRequest();
                req.ReturnDynamicEntities       =   isDynamic;
                req.RollupType                  =   RollupType.Related;
                TargetRollupDynamic target      =   new TargetRollupDynamic();
                target.EntityName               =   entityNm;
                target.EntityId                 =   Id;
                target.Query                    =   quer;
                req.Target                      =   target;
                if (!admin)
                        rr                      =   (RollupResponse)userService3.ExecuteRaw(req);
                else    rr                      =   (RollupResponse)adminService3.ExecuteRaw(req);
                BusinessEntityCollection bu     =   rr.BusinessEntityCollection;
                if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 RollupRaw END count: {0}", ((bu != null) && ( bu.BusinessEntities != null )) ? (bu.BusinessEntities.GetUpperBound(0)+1):0),CRMTraceSwitch.Sw.Info);
            }
            catch (SoapException sx)
            {
                string msg      =   string.Format("[E]CRMWrapper3 RollupRaw sex: {0}-{1}", sx, sx.Detail.InnerText);
                string errMsg   =   CRMUtil.GetErrorCode(sx);
                if ( errMsg == CrmStr.ObjectNotFound )
                    msg         =   "[E]CRMWrapperBase RollupRaw Object not found exception.";
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                if ( errMsg == CrmStr.ObjectNotFound )
                    throw new CRMNotFoundException(msg, sx);
				throw new CRMWrapperException(msg, sx);
            }
            catch (Exception ex)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 RollupRaw ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                throw;
            }
            return rr;
        }

        #endregion Rollup operations


        #region Implementation specific methods to avoid the encapsulation with Crmxxx objects

        public Response userExecuteRaw(Request r)
        {
            Response rep    =   null;
            try
            {
                rep         =   userService3.ExecuteRaw(r);
            }
            catch (SoapException sx)
            {
                string msg  =   string.Format("[E]CRMWrapper3 userExecuteRaw ex: {0}-{1}", sx, sx.Detail.InnerText);
                string errMsg   =   CRMUtil.GetErrorCode(sx);
                if ( errMsg == CrmStr.ObjectNotFound )
                    msg     =   "[E]CRMWrapper3 userExecuteRaw Object not found exception.";
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                if ( errMsg == CrmStr.ObjectNotFound )
                    throw new CRMNotFoundException(msg, sx);
                throw new CRMWrapperException(msg, sx);
            }
            catch (Exception ex)
            {
                string msg  =   string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 userExecuteRaw ex: {0}", ex);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine(msg,CRMTraceSwitch.Sw.Info);
                throw;
            }
            return rep;
        }

        public Response userUpdateRaw(UpdateRequest r)
        {
            Response rep    =   null;
            try
            {
                rep         =   userService3.ExecuteRaw(r);
            }
            catch (SoapException sx)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 userUpdate ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException("userUpdate soap: " + sx.Detail.InnerText, sx);
            }
            catch (Exception ex)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 userUpdate ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                throw;
            }
            return rep;
        }

        public Response CreateRaw(Request create,bool isAdmin)
        {
            Response rep = null;
            try
            {
                if ( isAdmin) 
                    rep = adminService3.ExecuteRaw(create);
                else 
                    rep = userService3.ExecuteRaw(create);
            }
            catch (SoapException sx)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 Create isAdmin: {0}, ex: {1}-{2}",isAdmin,sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException("userCreate soap: " + sx.Detail.InnerText, sx);
            }
            catch (Exception ex)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 Create isAdmin: {0}, ex: {1}",isAdmin,ex),CRMTraceSwitch.Sw.Info);
                throw;
            }
            return rep;
        }

        public Response userDeleteRaw(Request delete)
        {
            Response rep = null;
            try
            {
                rep = userService3.ExecuteRaw(delete);
            }
            catch (SoapException sx)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 userDelete ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException("userDelete sex", sx);
            }
            catch (CRMWrapperException)
            {
                throw;
            }
            catch (Exception ex)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 userDelete ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException("userDelete ex", ex);
            }
            return rep;
        }

        public Response adminExecuteRaw(Request r)
        {
            Response rep    =   null;
            try
            {
                rep         =   adminService3.ExecuteRaw(r);
            }
            catch (SoapException sx)
            {
                string msg  =   string.Format("[E]CRMWrapper3 AdminExecuteRaw ex: {0}-{1}", sx, sx.Detail.InnerText);
                string errMsg   =   CRMUtil.GetErrorCode(sx);
                if ( errMsg == CrmStr.ObjectNotFound )
                    msg     =   "[E]CRMWrapper3 AdminExecute Object not found exception.";
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                if ( errMsg == CrmStr.ObjectNotFound )
                    throw new CRMNotFoundException(msg, sx);
                throw new CRMWrapperException(msg, sx);
            }
            catch (CRMWrapperException)
            {
                throw;
            }
            catch (Exception ex)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 AdminExecuteRaw ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException("adminExecute ex", ex);
            }
            return rep;
        }

        public Response adminAdminExecuteRaw(Request r)
        {
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 adminAdminExecute BEG Request: {0}", r),CRMTraceSwitch.Sw.Info);
            Response rep = null;
            try
            {
                    rep = adminAdminService3.ExecuteRaw(r);
            }
            catch (SoapException sx)
            {
                string msg  =   string.Format("[E]CRMWrapper3 adminAdminExecuteRaw ex: {0}-{1}", sx, sx.Detail.InnerText);
                string errMsg   =   CRMUtil.GetErrorCode(sx);
                if ( errMsg == CrmStr.ObjectNotFound )
                    msg     =   "[E]CRMWrapper3 adminAdminExecuteRaw Object not found exception.";
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                if ( errMsg == CrmStr.ObjectNotFound )
                    throw new CRMNotFoundException(msg, sx);
                throw new CRMWrapperException(msg, sx);
            }
            catch (Exception ex)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 adminAdminExecute ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException("adminAdminExecute ex", ex);
            }
            return rep;
        }

        public void Update(BusinessEntity be, bool admin)
        {
            try
            {
                if (!admin)
                        userService3.UpdateRaw(be);
                else    adminService3.UpdateRaw(be);
            }
            catch (SoapException sx)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 Update ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException("Update soap: " + sx.Detail.InnerText, sx);
            }
            catch (Exception ex)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 Update ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                throw;
            }
        }

        public BusinessEntity RetrieveRaw(string typename,Guid Id,ColumnSetBase col,bool admin)
        {
            BusinessEntity bu = null;
            try
            {
                if (!admin)
                     bu     =   userService3.RetrieveRaw(typename, Id,col);
                else bu     =   adminService3.RetrieveRaw(typename,Id,col);
            }
            catch (SoapException sx)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 Retrieve ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException("Retrieve soap: " + sx.Detail.InnerText, sx);
            }
            catch (Exception ex)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 Retrieve ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                throw;
            }
            return bu;
        }

        public BusinessEntityCollection RetrieveMultipleRaw(QueryBase quer, bool admin)
        {
            BusinessEntityCollection bu = null;

            try
            {
                if (!admin)
                        bu = userService3.RetrieveMultipleRaw(quer);
                else    bu = adminService3.RetrieveMultipleRaw(quer);
            }
            catch (SoapException sx)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 RetrieveMultiple ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException("RetrieveMultiple soap: " + sx.Detail.InnerText, sx);
            }
            catch (Exception ex)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 RetrieveMultiple ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                throw;
            }
            return bu;
        }

        public Guid Create(BusinessEntity be,bool admin)
        {
            Guid wid = Guid.Empty;
            try
            {
                if ( !admin )
                    wid = userService3.CreateRaw(be);
                else
                    wid = adminService3.CreateRaw(be);
            }
            catch (SoapException sx)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 Create ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException("Create soap: " + sx.Detail.InnerText, sx);
            }
            catch (Exception ex)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 Create ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                throw;
            }
            return wid;
		}

		public EntityMetadata internalRetrieveEntityMetadataRaw(string entityName, EntityFlags f, bool isAdmin)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 InternalRetrieveEntityMetadataRaw  entityName: {0}, EntityItems: {1}, isAdmin: {2}", entityName, f,isAdmin),CRMTraceSwitch.Sw.Info);
			try
			{
				if (isAdmin)
					return adminMetaService3.RetrieveEntityMetadataRaw(entityName, f);
				return userMetaService3.RetrieveEntityMetadataRaw(entityName, f);
			}
			catch (SoapException sx)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 RetrieveEntityMetadata  ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException("RetrieveEntityMetadata Sx", sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 RetrieveEntityMetadata ex: {0}", ex),CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException("RetrieveEntityMetadata ex", ex);
			}
		}

		public AttributeMetadata internalRetrieveAttributeMetadataRaw(string entityName, string attributeName,bool isAdmin)
        {
			if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 internalRetrieveAttributeMetadata  entityName: {0}, attributeName: {1}, isAdmin: {2}", entityName,attributeName,isAdmin),CRMTraceSwitch.Sw.Info);
			try
			{
				if (isAdmin )
					return adminMetaService3.RetrieveAttributeMetadataRaw(entityName,attributeName);
			    return userMetaService3.RetrieveAttributeMetadataRaw(entityName,attributeName);
			}
			catch (SoapException sx)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 internalRetrieveAttributeMetadata  ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException("internalRetrieveAttributeMetadata Sx", sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 internalRetrieveAttributeMetadata ex: {0}", ex),CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException("internalRetrieveAttributeMetadata ex", ex);
			}
        }

        #endregion Implementation specific methods


        #region Utilities


        public override InternalRetrieveMultipleRequest MakeRetrieveMultipleRequest(InternalQueryExpression query, bool isDynamic)
        {
            QueryExpression Query           =   (QueryExpression)query;
			if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 MakeRetrieveMultipleRequest Query entityName: {0}, cols: {1}, isDynamic: {2}",Query.EntityName,Query.ColumnSet,isDynamic),CRMTraceSwitch.Sw.Info);
            RetrieveMultipleRequest req     =   new RetrieveMultipleRequest();
            req.Query                       =   Query;
            req.ReturnDynamicEntities       =   isDynamic;
            return new InternalRetrieveMultipleRequest(req);
        }

        public override InternalTargetCompoundDynamic MakeTargetCompoundDynamic(InternalDynamicEntity entity,InternalDynamicEntity[] childs)
        {
            TargetCompoundDynamic target    =   new TargetCompoundDynamic();
            target.Entity                   =   (DynamicEntity)entity.Content;
            DynamicEntity[] ch              =   new DynamicEntity[childs.Length];
            for(int i=0; i < childs.Length; i++)
            {
                ch[i]                       =   (DynamicEntity)childs[i].Content;
            }
            target.ChildEntities            =   ch;
            return new InternalTargetCompoundDynamic(target);
        }

        public override InternalTargetCompoundDynamic MakeTargetCompoundDynamic(DynEntity entity,List<DynEntity> childs)
        {
			if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 MakeTargetCompoundDynamic BEG entity: {0}, count: {1}", entity.SchemaName,childs.Count),CRMTraceSwitch.Sw.Info);
            TargetCompoundDynamic target    =   MakeTargetCompoundDynamicRaw(entity,childs);
            return new InternalTargetCompoundDynamic(target);
        }

        public TargetCompoundDynamic MakeTargetCompoundDynamicRaw(DynEntity entity,List<DynEntity> childs)
        {
			if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 MakeTargetCompoundDynamic BEG entity: {0}, count: {1}", entity.SchemaName,childs.Count),CRMTraceSwitch.Sw.Info);
            TargetCompoundDynamic target    =   new TargetCompoundDynamic();
            target.Entity                   =   ToDynamicEntityRaw(entity);
            DynamicEntity[] ch              =   new DynamicEntity[childs.Count];
            for(int i=0; i < childs.Count; i++)
            {
                ch[i]                       =   ToDynamicEntityRaw(childs[i]);
            }
            target.ChildEntities            =   ch;
            return target;
        }


        /// <summary>
        /// Find user by its name
        /// </summary>
        systemuser GetUserByDomainName(string name)
        {
            systemuser currentUser				=   null;
            try
            {
                QueryExpression qe				=   new QueryExpression();
                qe.EntityName					=   CrmStr.systemuser;
                qe.ColumnSet					=   new AllColumns();
                
                ConditionExpression ce			=   new ConditionExpression();
                ce.AttributeName				=   CrmStr.domainname;
                ce.Operator						=   ConditionOperator.Equal;
                ce.Values						=   new object[] { name };

                qe.Criteria						=   new FilterExpression();
                // Set the properties of the filter.
                qe.Criteria.FilterOperator		=   LogicalOperator.And;
                qe.Criteria.Conditions			=   new ConditionExpression[] { ce };

                // Create the Request Object
                RetrieveMultipleRequest retrievePrincipal = new RetrieveMultipleRequest();

                // Set the Request Object's Properties
                retrievePrincipal.Query			=   qe;

                // Execute the Request
                RetrieveMultipleResponse principalResponse = (RetrieveMultipleResponse)adminAdminService3.ExecuteRaw(retrievePrincipal);
                BusinessEntity[] bu				=   principalResponse.BusinessEntityCollection.BusinessEntities;
				int sz							=	bu.GetUpperBound(0);
				if ( sz >= 0)
				{
					currentUser					= (systemuser)bu[0];
					if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetUserByDomainName upper bound read: {0}, UserName : {1}, currentUser.domainname: '{2}'", sz,name, currentUser.domainname),CRMTraceSwitch.Sw.Info);
					return currentUser;
				}
            }
            catch (CRMWrapperException)
            {
                throw;
            }
            catch (Exception ex)
            {
                string msg  =   string.Format("[E]CRMWrapper3 GetUserByDomainName ex: {0}", ex);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException(msg, ex);
            }
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetUserByDomainName UserName : {0}, currentUser null", name),CRMTraceSwitch.Sw.Info);
            return null;
        }

        /// <summary>
        /// Find user by its domain name
        /// </summary>
        public override ADNDynSystemUser GetUserByDomainName2(string name)
        {
            ADNDynSystemUser currentUser	    =   null;
            try
            {
                currentUser					=   Util.FindSystemUserByDomainName(name,true);
				if ( currentUser != null )
				{
					if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetUserByDomainName2 name: {0}, currentUser.domainname: '{1}'", name, currentUser.domainname),CRMTraceSwitch.Sw.Info);
					return currentUser;
				}
            }
            catch (SoapException sx)
            {
                string msg  =   string.Format("[E]CRMWrapper3 GetUserByDomainName2  ex: {0}-{1}", sx, sx.Detail.InnerText);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException(msg, sx);
            }
            catch (CRMWrapperException)
            {
                throw;
            }
            catch (Exception ex)
            {
                string msg  =   string.Format("[E]CRMWrapper3 GetUserByDomainName2 ex: {0}", ex);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException(msg, ex);
            }
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetUserByDomainName2 DomainName: {0}, currentUser null.", name),CRMTraceSwitch.Sw.Info);
            return null;
        }


        /// <summary>
        /// Find user by its CRM Guid
        /// </summary>
        systemuser GetUserById(Guid uId)
        {
    		if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetUserById BEG UserId : {0}", uId),CRMTraceSwitch.Sw.Info);
            systemuser currentUser					= null;
            try
            {
				AllColumns cols						= new AllColumns();
				TargetRetrieveSystemUser target		= new TargetRetrieveSystemUser();
				target.EntityId						= uId;
				RetrieveRequest retrieve			= new RetrieveRequest();
				retrieve.Target						= target;
				retrieve.ColumnSet					= cols;

				// Execute the request.
				RetrieveResponse retrieved			= (RetrieveResponse)adminAdminService3.ExecuteRaw(retrieve);				
                currentUser							= (systemuser)retrieved.BusinessEntity ;
				if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetUserById UserId : {0} - {1}", uId,currentUser.domainname),CRMTraceSwitch.Sw.Info);
            }
            catch (SoapException sx)
            {
                string msg                          =   string.Format("[E]CRMWrapper3 GetUserById ex: {0}-{1}", sx, sx.Detail.InnerText);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException(msg, sx);
            }
            catch (CRMWrapperException)
            {
                throw;
            }
            catch (Exception ex)
            {
                string msg                          =   string.Format("[E]CRMWrapper3 GetUserById ex: {0}", ex);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException(msg, ex);
            }
            return currentUser;
        }

        /// <summary>
        /// Find user by its CRM Guid
        /// </summary>
        public override ADNDynSystemUser GetUserById2(Guid uId)
        {
    		if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetUserById2 BEG UserId : {0}", uId),CRMTraceSwitch.Sw.Info);
            ADNDynSystemUser currentUser		    =   null;
            try
            {
                currentUser                         =   new ADNDynSystemUser(this,uId);
                bool success                        =   currentUser.adminRetrieve();
				if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetUserById2 UserId : {0} - {1}", uId,currentUser.domainname),CRMTraceSwitch.Sw.Info);
            }
            catch (SoapException sx)
            {
                string msg                          =   string.Format("[E]CRMWrapper3 GetUserById2 ex: {0}-{1}", sx, sx.Detail.InnerText);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException(msg, sx);
            }
            catch (CRMWrapperException)
            {
                throw;
            }
            catch (Exception ex)
            {
                string msg                          =   string.Format("[E]CRMWrapper3 GetUserById2 ex: {0}", ex);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException(msg, ex);
            }
            return currentUser;
        }

		#endregion Utilities

		#region Permissions nand Privileges related functions

		/// <summary>
        /// Retrieve all the privileges for the specified role
        /// </summary>
        RolePrivilege[] GetRolePrivileges(role wrole)
        {
            string ckey					= string.Format("GetRolePrivileges_{0}_{1}_{2}", userId, wrole,CrmVersion);
            if (CurrentCache.Exists(ckey))
                return (RolePrivilege[])CurrentCache.Get(ckey);
            // Create the request.
            RetrieveRolePrivilegesRoleRequest retrieve      = new RetrieveRolePrivilegesRoleRequest();
            retrieve.RoleId				                    = wrole.roleid.Value;
            RetrieveRolePrivilegesRoleResponse retrieved    = null;
            // Execute the request.
            try
            {
                retrieved				= (RetrieveRolePrivilegesRoleResponse)adminAdminService3.ExecuteRaw(retrieve);
            }
            catch (CRMWrapperException wx)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetRolePrivileges ex: {0}}", wx),CRMTraceSwitch.Sw.Info);
                throw;
            }
            catch (SoapException sx)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetRolePrivileges ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
                throw;
            }
            catch (Exception ex)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetRolePrivileges ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                throw;
            }

            CurrentCache.Insert(ckey,retrieved.RolePrivileges);
            return retrieved.RolePrivileges;
        }

        /// <summary>
        /// Retrieve a privilege to get its name
        /// </summary>
        privilege GetPrivilege(Guid id)
        {
            privilege p							= null;
            try
            {
                TargetRetrievePrivilege target	= new TargetRetrievePrivilege();
                target.EntityId					= id;
                
                RetrieveRequest retrievePrivilege = new RetrieveRequest();
                retrievePrivilege.ReturnDynamicEntities = false;
                retrievePrivilege.Target		= target;
                retrievePrivilege.ColumnSet		= new AllColumns();
                RetrieveResponse retrieved		= (RetrieveResponse)adminAdminService3.ExecuteRaw(retrievePrivilege);

                p                               = (privilege)retrieved.BusinessEntity;
            }
            catch (SoapException sx)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetPrivilege [{0}] soapex: {1}-{2}", id, sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
                throw;
            }
            catch (CRMWrapperException)
            {
                throw;
            }
            catch (Exception ex)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetPrivilege [{0}] ex: {1}", id,ex),CRMTraceSwitch.Sw.Info);
                throw;
            }
            return p;
        }
        

        /// <summary>
        /// Retrieve all the CRM Privileges
        /// </summary>
        public override InternalBusinessEntityCollection GetAllPrivileges()
        {
            // Create the request.
            RetrievePrivilegeSetRequest retrieve = new RetrievePrivilegeSetRequest();
            
            try
            {
                RetrievePrivilegeSetResponse retrieved = (RetrievePrivilegeSetResponse)adminService3.ExecuteRaw(retrieve);
                return   new InternalBusinessEntityCollection(retrieved.BusinessEntityCollection);
            }
            catch (SoapException sx)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetAllPrivileges ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
            }
            catch (CRMWrapperException wx)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetAllPrivileges ex: {0}}", wx),CRMTraceSwitch.Sw.Info);
                throw;
            }
            catch (Exception ex)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetAllPrivileges ex: {0}", ex),CRMTraceSwitch.Sw.Info);
            }
            return null;
        }

        /// <summary>
        /// Retrieve all the privileges for the entity
        /// </summary>
        /// <param name="entityName">Schema name of the entity</param>
        /// <returns>Privilege Array</returns>
        protected SecurityPrivilege[] GetEntityPrivilegesRaw(string entityName)
        {
			if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetEntityPrivilegesRaw  entityName: {0}", entityName),CRMTraceSwitch.Sw.Info);
			try
			{
                string ckey                         = string.Format("GetEntityPrivilegesRaw_{0}",CrmVersion).Replace(' ','_').Replace(',','_');
                if (CurrentCache.Exists(ckey))
                {
                    if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( "[V]CRMWrapper3 GetEntityPrivilegesRaw found in cache.",CRMTraceSwitch.Sw.Info);
                    return (SecurityPrivilege[])CurrentCache.Get(ckey);
                }
                EntityMetadata entity   =   internalRetrieveEntityMetadataRaw(entityName, EntityFlags.IncludePrivileges,true);
                SecurityPrivilege[] priv      =   entity.Privileges;
                if ( priv.Length > 0 )
                    CurrentCache.InsertLong(ckey, priv);
			    if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetEntityPrivilegesRaw  entityName: {0}, priv.Length: {1}", entityName, priv.Length),CRMTraceSwitch.Sw.Info);
                return priv;              
			}
			catch (SoapException sx)
			{
                string msg  =   string.Format("[E]CRMWrapper3 GetEntityPrivilegesRaw sex: {0}-{1}", sx, sx.Detail.InnerText);
				if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine(msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
                string msg  =   string.Format("[E]CRMWrapper3 GetEntityPrivilegesRaw ex: {0}", ex);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, ex);
			}
        }


        /// <summary>
        /// Retrieve all the Privileges for the connected user
        /// </summary>
        public override InternalRolePrivilegeArray GetUserPrivileges()
        {
            try
            {
                RetrieveUserPrivilegesRequest retrieve = new RetrieveUserPrivilegesRequest();
                retrieve.UserId = userId;
                // Execute the request.
                RetrieveUserPrivilegesResponse retrieved = (RetrieveUserPrivilegesResponse)adminAdminService3.ExecuteRaw(retrieve);
                return new InternalRolePrivilegeArray (retrieved.RolePrivileges);

            }
            catch (SoapException sx)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetUserPrivileges ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException("GetUserPrivileges Sx", sx);
            }
            catch (CRMWrapperException wx)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetUserPrivileges ex: {0}}", wx),CRMTraceSwitch.Sw.Info);
                throw;
            }
            catch (Exception ex)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetUserPrivileges ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException("GetUserPrivileges ex", ex);
            }
        }

        /// <summary>
        /// Get the connected user's AccessRights for a specific occurence of an entity
        /// Insert it in cache to improve speed
        /// TDB set a dependency for this in the cache
        /// </summary>
        public override InternalCrmAccessRights GetAccessRights(string EntName,Guid wGuid)
        {
            AccessRights r  = AccessRights.ReadAccess;
            string ckey = string.Format("GetAccessRights_{0}_{1}_{2}_{3}",
                new object[]{EntName, wGuid, userId,CrmVersion});
            if (CurrentCache.Exists(ckey))
                return (InternalCrmAccessRights)(int)(AccessRights)CurrentCache.Get(ckey);
            
            try
            {
                // Create the SecurityPrincipal object.
                // This class references the user whose access is being checked.
                SecurityPrincipal principal =   new SecurityPrincipal();

                // Set the properties of the SecurityPrincipal object.
                // Type is the typecode of the principalid.
                principal.Type              =   SecurityPrincipalType.User;
                // PrincipalId is the GUID of the user whose access is being checked.
                principal.PrincipalId       =   userId;

                // Create the target for the request.
                TargetOwnedDynamic owner    =   new TargetOwnedDynamic();
                owner.EntityName            =   EntName;
                // EntityId is the GUID of the account to which access is being checked.
                owner.EntityId              =   wGuid;

                // Create the request object.
                RetrievePrincipalAccessRequest access = new RetrievePrincipalAccessRequest();

                // Set the properties of the request object.
                access.Principal            =   principal;
                access.Target               =   owner;

                // Execute the request.
                RetrievePrincipalAccessResponse accessResponse = (RetrievePrincipalAccessResponse)adminService3.ExecuteRaw(access);
                r                           =   accessResponse.AccessRights;
                if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetAccesRights UserName : {0}, AccessRights : {1}",userName, r),CRMTraceSwitch.Sw.Info);
                CurrentCache.InsertLong(ckey, r);
            }
            catch (SoapException sx)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetAccesRights  ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
                throw;
            }
            catch (CRMWrapperException wx)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetAccesRights ex: {0}}", wx),CRMTraceSwitch.Sw.Info);
                throw;
            }
            catch (Exception ex)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetAccesRights ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                throw;
            }
            
        return (InternalCrmAccessRights)(int)r;
        }


        List<SecurityPrivilege> GetEntityPrivilegesForRight(string EntName,PrivilegeType pType)
        {
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3  GetEntityPrivilegesForRight BEG EntName: [{0}],  PrivilegeType: {1}", EntName,pType),CRMTraceSwitch.Sw.Info);
            SecurityPrivilege[] entPriv     =   GetEntityPrivilegesRaw(EntName);
            List<SecurityPrivilege> lst     =   new List<SecurityPrivilege>();
            foreach ( SecurityPrivilege sp in entPriv )
            {
                if ( sp.PrivilegeType == pType )
                {
                    lst.Add(sp);
                    if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3  GetEntityPrivilegesForRight found Name: {0}.", sp.Name),CRMTraceSwitch.Sw.Info);
                }
            }
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3  GetEntityPrivilegesForRight END EntName: {0},  PrivilegeType: {1}, Count: {2}", EntName,pType,lst.Count),CRMTraceSwitch.Sw.Info);
            return lst;
        }

        bool CheckPrivilege(string EntName, PrivilegeType pType)
        {
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3  CheckPrivilege BEG EntName: {0},  PrivilegeType: {1}", EntName,pType),CRMTraceSwitch.Sw.Info);
            List<SecurityPrivilege> entPriv     =   GetEntityPrivilegesForRight(EntName,pType);
            Dictionary<string,privilege> tbr    =   GetAllUserPrivileges();
            foreach ( SecurityPrivilege sp in entPriv )
            {
                if ( !tbr.ContainsKey(sp.Name) )
                {
                    if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3  CheckPrivilege END EntName: {0},  NOT found Name: {1}",EntName,sp.Name),CRMTraceSwitch.Sw.Info);
                    return false;
                }
            }
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3  CheckPrivilege END OK EntName: {0}.",EntName),CRMTraceSwitch.Sw.Info);
            return true;
        }

        /// <summary>
        /// Has the current user rigths on this entity type
        /// </summary>
        public override bool HasPermissions(string EntName, ADNCRMRights r )
        {
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 HasPermissions EntName: [{0}],  ADNCRMRights: {1}", EntName,r),CRMTraceSwitch.Sw.Info);
            //AccessRights userRights;
            bool ok = false;

            try
            {
                switch (r)
                {
                    case ADNCRMRights.ReadAccess:
                        ok          =   CheckPrivilege(EntName, PrivilegeType.Read);
                    break;
                    case ADNCRMRights.AddAccess:
                        ok          =   CheckPrivilege(EntName, PrivilegeType.Create);
                    break;
                    case ADNCRMRights.WriteAccess:
                        ok          =   CheckPrivilege(EntName, PrivilegeType.Write);
                    break;
                    case ADNCRMRights.DeleteAccess:
                        ok          =   CheckPrivilege(EntName, PrivilegeType.Delete);
                    break;
                    case ADNCRMRights.EditAccess:
                    case ADNCRMRights.AdminAccess:
                        {
                            string[] CRMRoles = GetStrUserRoles(userId);
                            if ( CRMTraceSwitch.Sw.TraceVerbose )
                                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 HasPermissions EntName: {0},  ADNCRMRights: {1}, CRMRoles.Length: {2}, Config.CRMAdminRole :{3}", new object[] { EntName, r, CRMRoles.Length, Config.CRMAdminRole }),CRMTraceSwitch.Sw.Info);
							for (int i = 0; i < CRMRoles.Length; i++)
							{
								string str	=	CRMRoles[i];
                                if ( CRMTraceSwitch.Sw.TraceVerbose )
                                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 HasPermissions EntName: {0},  ADNCRMRights: {1}, i: {2}, CRMRoles[i]: {3}", new object[]{EntName,r,i,str}),CRMTraceSwitch.Sw.Info);
                                if ( CRMTraceSwitch.Sw.TraceVerbose )
                                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 HasPermissions EntName: {0},  ADNCRMRights: {1}, i: {2}, CRMRoles[i]: '{3}', Config.CRMAdminRole: '{4}'", new object[]{EntName,r,i,str,Config.CRMAdminRole}),CRMTraceSwitch.Sw.Info);
								if ( str == Config.CRMAdminRole )
								{
									ok = true;
									break;
								}
							}
                            break;
                        }
                }
            }
            catch (SoapException sx)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 HasPermissions  SoapException : {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
                throw;
            }
            catch (CRMWrapperException wx)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 HasPermissions ex: {0}}", wx),CRMTraceSwitch.Sw.Info);
                throw;
            }
            catch (Exception ex)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 HasPermissions ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                throw;
            }
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 HasPermissions result: {2}, {4}-{3} ,typename : {0}, ADNCRMRights : {1}", new object[] { EntName, r, ok, userId,userName }),CRMTraceSwitch.Sw.Info);
            return ok;
        }
        

        /// <summary>
        /// Liste des Privileges de l'utilisateur sous forme d'un dictionnaire
        /// </summary>
        Dictionary<string, privilege>GetAllUserPrivileges()
        {
            string ckey                         = string.Format("GetAllUserPrivileges_{0}_{1}", userId, CrmVersion).Replace(' ','_').Replace(',','_');
            if (CurrentCache.Exists(ckey))
            {
                if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( "[V]CRMWrapper3 GetAllUserPrivileges found in cache.",CRMTraceSwitch.Sw.Info);
                return (Dictionary<string, privilege> )CurrentCache.Get(ckey);
            }
            Dictionary<string, privilege> dicPriv   =   new Dictionary<string, privilege>();
            try
            {
                QueryExpression qe				    =   new QueryExpression();
                qe.EntityName					    =   CrmStr.privilege;
                qe.ColumnSet					    =   new AllColumns();

                LinkEntity le                       =   new LinkEntity();
                le.LinkFromEntityName			    =   CrmStr.privilege;
                le.LinkFromAttributeName		    =   CrmStr.privilegeid;
                le.LinkToEntityName				    =   CrmStr.roleprivileges;
                le.LinkToAttributeName			    =   CrmStr.privilegeid;

                LinkEntity le0					    =   new LinkEntity();
                le0.LinkFromEntityName			    =   CrmStr.roleprivileges;
                le0.LinkFromAttributeName		    =   CrmStr.roleid;
                le0.LinkToEntityName			    =   CrmStr.systemuserroles;
                le0.LinkToAttributeName			    =   CrmStr.roleid;

                LinkEntity le2					    =   new LinkEntity();
                le2.LinkFromEntityName			    =   CrmStr.systemuserroles;
                le2.LinkFromAttributeName		    =   CrmStr.systemuserid;
                le2.LinkToEntityName			    =   CrmStr.systemuser;
                le2.LinkToAttributeName			    =   CrmStr.systemuserid;

                ConditionExpression ce			    =   new ConditionExpression();
                ce.AttributeName				    =   CrmStr.systemuserid;
                ce.Operator						    =   ConditionOperator.Equal;
                ce.Values						    =   new object[] { userId };

                le2.LinkCriteria				    =   new FilterExpression();
                le2.LinkCriteria.Conditions		    =   new ConditionExpression[] { ce };

                le0.LinkEntities				    =   new LinkEntity[] { le2 };
                le.LinkEntities					    =   new LinkEntity[] { le0 };
                qe.LinkEntities					    =   new LinkEntity[] { le };

                // Create the Request Object
                RetrieveMultipleRequest retrievePrincipal = new RetrieveMultipleRequest();

                // Set the Request Object's Properties
                retrievePrincipal.Query			    =   qe;

                // Execute the Request
                RetrieveMultipleResponse principalResponse = (RetrieveMultipleResponse)adminAdminService3.ExecuteRaw(retrievePrincipal);
                BusinessEntity[] bu				=   principalResponse.BusinessEntityCollection.BusinessEntities;
                if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetAllUserPrivileges bu.Length: {0}", bu.Length),CRMTraceSwitch.Sw.Info);
                for (int i=0 ;  i < bu.Length ; i++ )
                {
                    privilege p					    =   (privilege)bu[i];
                    if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetAllUserPrivileges i: {0}, p.name: {1}", i, p.name),CRMTraceSwitch.Sw.Info);
                    if (!dicPriv.ContainsKey(p.name))
                    {
                        dicPriv.Add(p.name, p);
                        if ( CRMTraceSwitch.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetAllUserPrivileges UserName: {0}, privilege: {1}", userName, p.name),CRMTraceSwitch.Sw.Info);
                    }
                }
                if ( dicPriv.Count != 0 )
                    CurrentCache.InsertLong(ckey, dicPriv);
            }
            catch (SoapException sx)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetAllUserPrivileges  ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
                throw;
            }
            catch (CRMWrapperException wx)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetAllUserPrivileges ex: {0}}", wx),CRMTraceSwitch.Sw.Info);
                throw;
            }
            catch (Exception ex)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetAllUserPrivileges ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                throw;
            }
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetAllUserPrivileges END UserName: {0}, Count: {1}", userName, dicPriv.Count),CRMTraceSwitch.Sw.Info);
            return dicPriv;
        }


        
		#endregion Permissions and Privileges related functions

		#region BusinessUnits related functions

		/// <summary>
		/// Retrieve all Business Units using admin call, insert them in a sorted dictionnary
		/// </summary>
		public override SortedDictionary<Guid,ADNDynBusinessUnit> GetAllBusinessUnits()
		{
            string ckey                     =   string.Format("GetAllBusinessUnits_{0}_{1}",OrganizationName,CrmVersion);
            if (CurrentCache.Exists(ckey))
                return (SortedDictionary<Guid,ADNDynBusinessUnit>)CurrentCache.Get(ckey);
            BusinessEntity[] bu = null;
			SortedDictionary<Guid,ADNDynBusinessUnit> DicBu	=	new SortedDictionary<Guid,ADNDynBusinessUnit>();
            try
            {
				QueryExpression qe		    =   new QueryExpression();
                qe.EntityName			    =   EntityName.businessunit.ToString();
                qe.ColumnSet			    =   new AllColumns();

                ConditionExpression ce		=   new ConditionExpression();
                ce.AttributeName			=   CrmStr.isdisabled;
                ce.Operator					=   ConditionOperator.NotEqual;
                ce.Values                   =   new object[]{true};

                qe.Criteria					=   new FilterExpression();
                qe.Criteria.FilterOperator	=   LogicalOperator.And;
                qe.Criteria.Conditions		=   new ConditionExpression[] { ce };

                RetrieveMultipleRequest retrievePrincipal = new RetrieveMultipleRequest();

                // Set the Request Object's Properties
                retrievePrincipal.Query		=   qe;
                retrievePrincipal.ReturnDynamicEntities =   true;

                // Execute the Request
                RetrieveMultipleResponse principalResponse = (RetrieveMultipleResponse)adminService3.ExecuteRaw(retrievePrincipal);
                bu						    =	principalResponse.BusinessEntityCollection.BusinessEntities;
				int nb					    =	bu.GetUpperBound(0);
                if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetAllBusinessUnits upperBound(0): {0}", nb),CRMTraceSwitch.Sw.Info);
				for (int i = 0; i <= nb; i++)
				{
					DynamicEntity    b		=   (DynamicEntity)(bu[i]);
					InternalDynamicEntity n =   new InternalDynamicEntity(b);
                    ADNDynBusinessUnit dbu  =   new ADNDynBusinessUnit(this,n);
                    if ( dbu.parentbusinessunitid == Guid.Empty  )
                        _InnerBusinessUnit  =   dbu;
					DicBu.Add(dbu.businessunitid, dbu);
				}
				if ( DicBu.Count > 0 )
                    CurrentCache.Insert(ckey, DicBu);
            }
            catch (SoapException sx)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetAllBusinessUnits  ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
                throw;
            }
            catch (CRMWrapperException )
            {
                throw;
            }
            catch (Exception ex)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetAllBusinessUnits ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                throw;
            }
			return DicBu;
		}

		/// <summary>
		/// Find a Bu using its Guid
		/// </summary>
		public override ADNDynBusinessUnit GetBusinessUnit(Guid businessunitid)
		{
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetBusinessUnit businessunitid: {0}",businessunitid),CRMTraceSwitch.Sw.Info);
			SortedDictionary<Guid,ADNDynBusinessUnit> dicBu	= GetAllBusinessUnits();
			if ( dicBu.ContainsKey(businessunitid) )
				return dicBu[businessunitid];
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetBusinessUnit NOT FOUND businessunitid: {0}",businessunitid),CRMTraceSwitch.Sw.Info);
			return null;
		}

		/// <summary>
		/// Find Name for a Bu given its Guid
		/// </summary>
		public override string GetBusinessUnitName(Guid businessunitid)
		{
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetBusinessUnitName businessunitid: {0}",businessunitid),CRMTraceSwitch.Sw.Info);
			SortedDictionary<Guid,ADNDynBusinessUnit> dicBu	= GetAllBusinessUnits();
			if ( dicBu.ContainsKey(businessunitid) )
				return dicBu[businessunitid].name;
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetBusinessUnitName NOT FOUND businessunitid: {0}",businessunitid),CRMTraceSwitch.Sw.Info);
			return string.Empty;
		}
		#endregion BusinessUnits related functions

        #region roles related functions

        /// <summary>
        /// Renvoie la liste de tous les roles sous forme d'un tableau de roles
        /// </summary>
        public override InternalBusinessEntityArray GetAllRoles()
        {
            string ckey						= string.Format("GetAllRoles_{0}_{1}",OrganizationName,CrmVersion);
            if (CurrentCache.Exists(ckey))
                return (InternalBusinessEntityArray)CurrentCache.Get(ckey);
            InternalBusinessEntityArray bu				= null;

            try
            {
                QueryExpression qe			=   new QueryExpression();
                qe.EntityName				=   EntityName.role.ToString();
                qe.ColumnSet				=   new AllColumns();

                ConditionExpression ce		=   new ConditionExpression();
                ce.AttributeName			=   CrmStr.roleid;
                ce.Operator					=   ConditionOperator.NotNull;

                qe.Criteria					=   new FilterExpression();

                qe.Criteria.FilterOperator	=   LogicalOperator.And;
                qe.Criteria.Conditions		=   new ConditionExpression[] { ce };

                RetrieveMultipleRequest retrievePrincipal = new RetrieveMultipleRequest();

                retrievePrincipal.Query		=   qe;

                RetrieveMultipleResponse principalResponse = (RetrieveMultipleResponse)adminService3.ExecuteRaw(retrievePrincipal);
                bu = new InternalBusinessEntityArray(principalResponse.BusinessEntityCollection.BusinessEntities);
                if ( principalResponse.BusinessEntityCollection.BusinessEntities.GetUpperBound(0) >= 0 )
                    CurrentCache.Insert(ckey, bu);
            }
            catch (SoapException sx)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetAllRoles  ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
                throw;
            }
            catch (CRMWrapperException )
            {
                throw;
            }
            catch (Exception ex)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetAllRoles ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                throw;
            }
            return bu;
        }

		/// <summary>
        /// Renvoie la liste de tous les noms de roles 
        /// sous forme d'un tableau de strings
        /// </summary>
        public override string[] GetStrAllRoles()
        {
            BusinessEntity[] bu = null;

            try
            {
                InternalBusinessEntityArray b0   =   GetAllRoles();
                bu  =   (BusinessEntity[])b0.Content;
            }
            catch (SoapException sx)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetStrRoles  ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException("GetStrAllRoles Sx", sx);
            }
            catch (CRMWrapperException)
            {
                throw;
            }
            catch (Exception ex)
            {
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetStrRoles ex: {0}", ex),CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException("GetStrAllRoles ex", ex);
            }

            SortedDictionary<string, role> dicRole = new SortedDictionary<string, role>();
            foreach (BusinessEntity b in bu)
            {
                role r				= (role)b;
				string strBu		= GetBusinessUnitName(r.businessunitid.Value);
				string roleName		= string.Format("{0}.{1}",strBu,r.name);
                if (!dicRole.ContainsKey(roleName))
                {
                    dicRole.Add(roleName, r);
                    if ( CRMTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 UserName : {0}, role : {1}", userName, roleName),CRMTraceSwitch.Sw.Info);
                }
            }
            string[] roles			= new string[dicRole.Count];
            int i					= 0;
            StringBuilder sb		= new StringBuilder();
            foreach (KeyValuePair<string, role> kvp in dicRole)
            {
                roles[i++]			=   kvp.Key;
                if ( CRMTraceSwitch.Sw.TraceVerbose )
                    sb.AppendFormat("{0}-", kvp.Key);
            }
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetStrAllRoles  {0}, nbroles : {1}", sb.ToString(), i),CRMTraceSwitch.Sw.Info);
            return roles;
        }

        /// <summary>
        /// Return list of user roles
        /// </summary>
        public override InternalBusinessEntityArray GetUserRoles(Guid userId2Test)
        {
            string ckey						= string.Format("GetUserRoles_{0}_{1}",userId2Test,CrmVersion);
            if (CurrentCache.Exists(ckey))
            {
                if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetUserRoles found in cache ckey: {0}", ckey),CRMTraceSwitch.Sw.Info);
                return (InternalBusinessEntityArray)CurrentCache.Get(ckey);
            }
            InternalBusinessEntityArray bu	    = null;
            try
            {
                QueryExpression qe			= new QueryExpression();
                qe.EntityName				= EntityName.role.ToString();
                qe.ColumnSet				= new AllColumns();

                LinkEntity le				= new LinkEntity();
                le.LinkFromEntityName		= qe.EntityName;
                le.LinkFromAttributeName	= CrmStr.roleid;
                le.LinkToEntityName			= CrmStr.systemuserroles;
                le.LinkToAttributeName		= CrmStr.roleid;

                LinkEntity le2				= new LinkEntity();
                le2.LinkFromEntityName		= CrmStr.systemuserroles;
                le2.LinkFromAttributeName	= CrmStr.systemuserid;
                le2.LinkToEntityName		= EntityName.systemuser.ToString();
                le2.LinkToAttributeName		= CrmStr.systemuserid;

                ConditionExpression ce		= new ConditionExpression();
                ce.AttributeName			= CrmStr.systemuserid;
                ce.Operator					= ConditionOperator.Equal;
                ce.Values					= new object[] { userId2Test };

                le2.LinkCriteria			= new FilterExpression();
                le2.LinkCriteria.Conditions = new ConditionExpression[] { ce };

                le.LinkEntities				= new LinkEntity[] { le2 };
                qe.LinkEntities				= new LinkEntity[] { le };

                // Create the Request Object
                RetrieveMultipleRequest retrievePrincipal = new RetrieveMultipleRequest();

                // Set the Request Object's Properties
                retrievePrincipal.Query		= qe;

                // Execute the Request
                RetrieveMultipleResponse principalResponse = (RetrieveMultipleResponse)adminAdminService3.ExecuteRaw(retrievePrincipal);
                BusinessEntity[] bu0	    = principalResponse.BusinessEntityCollection.BusinessEntities;
                bu							= new InternalBusinessEntityArray(bu0);
                int nb						= bu0.GetUpperBound(0)+1;
                if ( nb > 0 )
                    CurrentCache.Insert(ckey, bu);
                if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetUserRoles END userId: {0}, nbRoles: {1}", userId2Test, nb),CRMTraceSwitch.Sw.Info);
            }
            catch (SoapException sx)
            {
                string msg  =   string.Format("[E]CRMWrapper3 GetUserRoles  ex: {0}-{1}", sx, sx.Detail.InnerText);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException(msg, sx);
            }
            catch (CRMWrapperException)
            {
                throw;
            }
            catch (Exception ex)
            {
                string msg  =   string.Format("[E]CRMWrapper3 GetUserRoles ex: {0}", ex);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException(msg, ex);
            }
            return bu;
        }

        // <summary>
        /// Build an array of strings with names of all roles attached to this user, each element is formated with as 'businessunit.rolename'
        /// </summary>
        public override string[] GetStrUserRoles(Guid userId2Test)
        {
            string ckey				= string.Format("GetStrUserRoles_{0}_{1}",userId2Test,CrmVersion);
            if (CurrentCache.Exists(ckey))
            {
                if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetStrUserRoles found in cache ckey: {0}", ckey),CRMTraceSwitch.Sw.Info);
                return (string[])CurrentCache.Get(ckey);
            }
            BusinessEntity[] bu = null;

            try
            {
                bu					= (BusinessEntity[])GetUserRoles(userId2Test).Content;
            }
            catch (SoapException sx)
            {
                string msg  =   string.Format("[E]CRMWrapper3 GetStrUserRoles  ex: {0}-{1}", sx, sx.Detail.InnerText);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException(msg, sx);
            }
            catch (CRMWrapperException)
            {
                throw;
            }
            catch (Exception ex)
            {
                string msg  =   string.Format("[E]CRMWrapper3 GetStrUserRoles ex: {0}", ex);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException(msg, ex);
            }
            string[] roles			= new string[0];
			string strr				= string.Empty;
            if (bu.GetUpperBound(0) >= 0)
            {
                StringBuilder sb    = new StringBuilder();
                foreach (BusinessEntity b in bu)
                {
                    role r          = (role)b;
					string strBu	= GetBusinessUnitName(r.businessunitid.Value);
                    sb.AppendFormat("{0}.{1};", strBu,r.name);
                }
                strr				= sb.ToString();
                roles               = strr.Split(";".ToCharArray());
                CurrentCache.Insert(ckey, roles);
            }
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetStrUserRoles END UserId : {0}, roles : '{1}'", userId2Test, strr),CRMTraceSwitch.Sw.Info);
            return roles;
		}

        /// <summary>
		/// Try to check if the role sent is amongst the roles of this user
		/// </summary>
        public override bool IsInCRMUserRoles(string role2Test,Guid userId2Test)
        {
			if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 IsInCRMUserRoles role2Test: {0}.",role2Test),CRMTraceSwitch.Sw.Info);
            bool ret			=	false;
            BusinessEntity[] bu = null;

            try
            {
                bu					= (BusinessEntity[])GetUserRoles(userId2Test).Content;
            }
            catch (SoapException sx)
            {
                string msg  =   string.Format("[E]CRMWrapper3 IsInCRMUserRoles ex: {0}-{1}", sx, sx.Detail.InnerText);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException(msg, sx);
            }
            catch (CRMWrapperException)
            {
                throw;
            }
            catch (Exception ex)
            {
                string msg  =   string.Format("[E]CRMWrapper3 IsInCRMUserRoles ex: {0}", ex);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException(msg, ex);
            }
			int idx		        =	role2Test.IndexOf('.');
			if ( idx != -1 )
				role2Test		=	role2Test.Substring(idx+1);
			if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 IsInCRMUserRoles reduced role2Test: {0}.",role2Test),CRMTraceSwitch.Sw.Info);
            if (bu.GetUpperBound(0) >= 0)
            {
                foreach (BusinessEntity b in bu)
                {
                    role r          = (role)b;
					if ( r.businessunitid.Value == businessUnitId && r.name == role2Test )
					{
						if ( CRMTraceSwitch.Sw.TraceVerbose )
                            Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 IsInCRMUserRoles role2Test: {0} found.",role2Test),CRMTraceSwitch.Sw.Info);
						ret			=	true;
						break;
					}
                }
            }
            if ( CRMTraceSwitch.Sw.TraceInfo )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 IsInCRMUserRoles END rols: '{0}', ret: {1}", role2Test, ret),CRMTraceSwitch.Sw.Info);
            return ret;
        }



		#endregion roles related functions

		#region Retrieving metadata
        
        public override string GetTimestamp()
        {
            const string noTmsp =   "No Time stamp in v3";
            return noTmsp;
        }
        
        
        Metadata internalRetrieveMetadataRaw(MetadataFlags f,bool isAdmin)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 internalRetrieveMetadataRaw  EntityFlags: {0}, isAdsmin: {1}", f,isAdmin),CRMTraceSwitch.Sw.Info);
			try
			{
				if (isAdmin)
					return adminMetaService3.RetrieveMetadataRaw(f);
				return userMetaService3.RetrieveMetadataRaw(f);
			}
			catch (SoapException sx)
			{
                string msg  =   string.Format("[E]CRMWrapper3 internalRetrieveMetadataRaw  ex: {0}-{1}", sx, sx.Detail.InnerText);
				if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
                string msg  =   string.Format("[E]CRMWrapper3 internalRetrieveMetadataRaw ex: {0}", ex);
				if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, ex);
			}
		}

        public override InternalMetadata internalRetrieveMetadata(EntityInternalItems f,bool isAdmin)
		{
			if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 internalRetrieveMetadata  EntityFlags: {0}, isAdsmin: {1}", f,isAdmin),CRMTraceSwitch.Sw.Info);
			try
			{
				if (isAdmin)
					return adminMetaService.RetrieveMetadata(f);
				return userMetaService.RetrieveMetadata(f);
			}
			catch (SoapException sx)
			{
                string msg  =   string.Format("[E]CRMWrapper3 internalRetrieveMetadata  ex: {0}-{1}", sx, sx.Detail.InnerText);
				if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
                string msg  =   string.Format("[E]CRMWrapper3 internalRetrieveMetadata ex: {0}", ex);
				if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( msg,CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException(msg, ex);
			}
		}

        /// <summary>
        /// Retrieve the object type code for the specified entity
        /// </summary>
        /// <param name="entityName">Schema name of the entity</param>
        /// <returns>Object type code of entity</returns>
        public override int GetObjectTypeCode(string entityName)
        {
			if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetObjectTypeCode  entityName: {0}", entityName),CRMTraceSwitch.Sw.Info);
			try
			{
                EntityMetadata entity       =   internalRetrieveEntityMetadataRaw(entityName, EntityFlags.EntityOnly,true);
			    int objectTypeCode          =   entity.ObjectTypeCode;              

                if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetObjectTypeCode  entityName: {0}, ObjectTypeCode: {1}", entityName, objectTypeCode),CRMTraceSwitch.Sw.Info);
                return objectTypeCode;              
			}
			catch (SoapException sx)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetObjectTypeCode  ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException("GetObjectTypeCode Sx", sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetObjectTypeCode ex: {0}", ex),CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException("GetObjectTypeCode ex", ex);
			}
        }

        /// <summary>
        /// Retrieve the display name for the specified entity
        /// </summary>
        /// <param name="entityName">Schema name of the entity</param>
        /// <returns>Display name of the entity</returns>
        public override string GetDisplayName(string entityName)
        {
			if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetDisplayName  entityName: {0}", entityName),CRMTraceSwitch.Sw.Info);
			try
			{
                EntityMetadata entity       =   internalRetrieveEntityMetadataRaw(entityName, EntityFlags.EntityOnly,true);
                string displayName          =   entity.DisplayName;              
			    if ( CRMTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetDisplayName  entityName: {0}, DisplayName: {1}", entityName,displayName),CRMTraceSwitch.Sw.Info);
                return displayName;              
			}
			catch (SoapException sx)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetDisplayName  ex: {0}-{1}", sx, sx.Detail.InnerText),CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException("GetDisplayName Sx", sx);
			}
			catch (CRMWrapperException)
			{
				throw;
			}
			catch (Exception ex)
			{
				if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 GetDisplayName ex: {0}", ex),CRMTraceSwitch.Sw.Info);
				throw new CRMWrapperException("GetDisplayName ex", ex);
			}
        }

        public override int IterateMetaEntities(EntityInternalItems f, bool isAdmin,bool customOnly,EntityNameDelegate fn)
        {
			if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 IterateMetaEntities BEG customOnly: {0}, isAdmin: {1}", customOnly, isAdmin),CRMTraceSwitch.Sw.Info);

            MetadataFlags fl    =   Crm3MetadataWebService.ConvertMetaDataFlag(f);
            Metadata metadata   =   internalRetrieveMetadataRaw(fl, isAdmin);

            // Iterate through all entities and only add custom entities
            int cnt                     =   0;
            // Iterate through all entities and only add custom entities
            for (int i = 0; i < metadata.Entities.Length; i++)
            {
                EntityMetadata em   =   metadata.Entities[i];
                if (em.IsCustomEntity && !string.IsNullOrEmpty(em.DisplayName))
                {
                    if ( em.DisplayName != null )
                         fn(em.Name,em.DisplayName);
                    else fn(em.Name,em.Name);
                    cnt++;
                }
                else if (CRMTraceSwitch.Sw.TraceVerbose)
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 IterateMetaEntities not retained entity : {0}", em.Name), CRMTraceSwitch.Sw.Info);
            }
			if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 IterateMetaEntities END Count: {0}.", cnt),CRMTraceSwitch.Sw.Info);
            return cnt;
        }

		#endregion Retrieving metadata

        #region special for DynEntity

        /// <summary>
        /// conversion between Crm Attributes types and .net types
        /// </summary>
        public Type ConvertAttributeType2Type(AttributeType EntAtt)
        {
            Type tmp;

            switch (EntAtt)
            {
                case AttributeType.DateTime:
                    tmp = typeof(System.DateTime);
                    break;

                case AttributeType.Boolean:
                    tmp = typeof(System.Boolean);
                    break;

                case AttributeType.Money:
                case AttributeType.Decimal:
                    tmp = typeof(System.Decimal);
                    break;

                case AttributeType.Status:
                case AttributeType.Picklist:
                case AttributeType.Integer:
                    tmp = typeof(System.Int32);
                    break;

                case AttributeType.PrimaryKey:
                case AttributeType.Owner:
                case AttributeType.Customer:
                case AttributeType.Lookup:
                case AttributeType.UniqueIdentifier:
                    tmp = typeof(System.Guid);
                    break;

                case AttributeType.Float:
                    tmp = typeof(System.Single);
                    break;

                default:
                    tmp = typeof(string);
                    break;
                }
            if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 ConvertAttributeType2Type AttributeType: {0}, Type: {1}", EntAtt,tmp),CRMDynTraceSwitch.Sw.Info);
            return tmp;
        }
        
        /// <summary>
        /// Creates a collection of PropertyDescriptors from an array of CRM attributes
        /// </summary>
        public override PropertyDescriptorCollection StaticCreatePropertyDescriptorCollection(EntityInternalMetadata attribs)
        {
            AttributeMetadata[] attributes          =   ((EntityMetadata)attribs.Content).Attributes;
            DynEntity.LocalPropertyDescriptor[] pds =   new DynEntity.LocalPropertyDescriptor[attributes.Length];

            // Populate the Property Descriptor collection with Property descriptors
            for (int i = 0; i < attributes.Length; i++)
            {
                AttributeMetadata d                 =   attributes[i];
                if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 StaticCreatePropertyDescriptorCollection Attribute  i={0}, Name: {1}, Type: {2}",i, d.Name,d.Type),CRMDynTraceSwitch.Sw.Info);
                if ( ( (d.DisplayMask & DisplayMasks.ObjectTypeCode) == DisplayMasks.ObjectTypeCode ) && ( d.Type == AttributeType.Picklist ) ) 
                     pds[i]       =   new DynEntity.LocalPropertyDescriptor(d.Name, typeof(string));
                else pds[i]                              = new DynEntity.LocalPropertyDescriptor(d.Name, ConvertAttributeType2Type(d.Type));
            }
            return new PropertyDescriptorCollection(pds);
        }

        public override PropertyDescriptorCollection CreatePropertyDescriptorCollection(EntityInternalMetadata attribs,DicProperties dicProperty,bool filterWithProperties)
        {
            DynEntity.LocalPropertyDescriptor[] pds =   null;
            AttributeMetadata[] attributes          =   ((EntityMetadata)attribs.Content).Attributes;

            if ( filterWithProperties && dicProperty.Count > 0 )
                    pds                     =   new DynEntity.LocalPropertyDescriptor[dicProperty.Count];
            else    pds                     =   new DynEntity.LocalPropertyDescriptor[attributes.Length];

            // Populate the Property Descriptor collection with Property descriptors
            int count                       =   0;
            for (int i = 0; i < attributes.Length; i++)
            {
                AttributeMetadata d         =   attributes[i];
                if (filterWithProperties && !dicProperty.ContainsKey(d.Name))
                    continue;
                if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 CreatePropertyDescriptorCollection Attribute  i={0}, Name: {1}, Type: {2}.",
                        count, d.Name,d.Type),CRMDynTraceSwitch.Sw.Info);
                // Bug ??? When EntityReference attribute is picklist , should be string
                if ( ( (d.DisplayMask & DisplayMasks.ObjectTypeCode) == DisplayMasks.ObjectTypeCode ) && ( d.Type == AttributeType.Picklist ) ) 
                     pds[count++]       =   new DynEntity.LocalPropertyDescriptor(d.Name, typeof(string));
                else pds[count++]       =   new DynEntity.LocalPropertyDescriptor(d.Name, ConvertAttributeType2Type(d.Type));
            }
            return new PropertyDescriptorCollection(pds);
        }
        
        /// <summary>
        /// Get the "value" of a property
        /// Based on the type of property, this method determines how to get the properties "value"
        /// </summary>
        public override object GetPropertyValue(InternalProperty prop)
        {
            return GetPropertyValueRaw((Property)prop.Content);
        }

        public object GetPropertyValueRaw(Property prop)
        {
            // Based on the property type, we will determine what data should be returned to the 
            // Grid for display.  This sample includes some hard-coded default behavior that may
            // or may not be approriate for your needs.

            Type propertyType = prop.GetType();

            if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 GetPropertyValue: {0}", propertyType),CRMDynTraceSwitch.Sw.Info);

            if (propertyType == typeof(StringProperty))
            {
                return ((StringProperty)prop).Value;
            }
            if (propertyType == typeof(CrmDateTimeProperty))
            {
                // Convert the CRM date into a System.DateTime
                CrmDateTimeProperty dprop       =   (CrmDateTimeProperty)prop;
                CRM3Server.CrmDateTime cdate    =   dprop.Value;
                if ( !string.IsNullOrEmpty(cdate.Value) )
                {
                    string dateTimeAsText       =   cdate.Value;
                    return DateTime.Parse(dateTimeAsText, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal);
                }
                return null; // ??? potential pb
            }
            if (propertyType == typeof(KeyProperty))
            {
                return ((KeyProperty)prop).Value.Value;
            }
            if (propertyType == typeof(LookupProperty))
            {
                return (((LookupProperty)prop).Value).Value;
            }
            if (propertyType == typeof(StateProperty))
            {
                return ((StateProperty)prop).Value;
            }
            if (propertyType == typeof(PicklistProperty))
            {
                return ((PicklistProperty)prop).Value.name;
            }
            if (propertyType == typeof(CrmMoneyProperty))
            {
                return ((CrmMoneyProperty)prop).Value.Value;
            }
            if (propertyType == typeof(CrmBooleanProperty))
            {
                return ((CrmBooleanProperty)prop).Value.Value;
            }

            if (propertyType == typeof(CrmDecimalProperty))
            {
                return ((CrmDecimalProperty)prop).Value.Value;
            }

            if (propertyType == typeof(CrmFloatProperty))
            {
                return ((CrmFloatProperty)prop).Value.Value;
            }

            if (propertyType == typeof(CrmNumberProperty))
            {
                return ((CrmNumberProperty)prop).Value.Value;
            }
            if (propertyType == typeof(CustomerProperty))
            {
                return ((CustomerProperty)prop).Value.Value;
            }
            if (propertyType == typeof(EntityNameReferenceProperty))
            {
                return ((EntityNameReferenceProperty)prop).Value.Value;
            }
            if (propertyType == typeof(OwnerProperty))
            {
                return ((OwnerProperty)prop).Value.Value;
            }
            if (propertyType == typeof(StatusProperty))
            {
                return ((StatusProperty)prop).Value.Value;
            }

            if (propertyType == typeof(UniqueIdentifierProperty))
            {
                return ((UniqueIdentifierProperty)prop).Value.Value;
            }
            // we return the Array length
            if (propertyType == typeof(DynamicEntityArrayProperty))
            {
                return ((DynamicEntityArrayProperty)prop).Value.Length;
            }
            // The property type is not supported
            string strerr   =   string.Format("DynEntity GetPropertyValue unsupported property: {0} type:{1}",prop.Name,propertyType.GetType().Name);
            if ( CRMDynTraceSwitch.Sw.TraceError )
                Trace.WriteLine(strerr,CRMDynTraceSwitch.Sw.Info);

            throw new CRMWrapperException(strerr);
        }

        public override void FillDicProperties(InternalDynamicEntity crmdEntity, InternalColumnSet CSel, DicProperties dicProperty)
        {
            DynamicEntity dEntity    =   (DynamicEntity)crmdEntity.Content;
            if (CRMDynTraceSwitch.Sw.TraceVerbose)
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 FillDicProperties BEG entity: {0}.",dEntity.Name), CRMDynTraceSwitch.Sw.Info);
            ColumnSet ColSel         =   (CSel == null) ? null:(ColumnSet)CSel;
            foreach (Property ep in dEntity.Properties)
            {
                // We only take selected columns
                if (ColSel != null)
                {
                    bool found = false;
                    for (int i = 0; i < ColSel.Attributes.Length; i++)
                    {
                        if (ColSel.Attributes[i] == ep.Name)
                        {
                            found = true;
                            break;
                        }
                    }
                    if (!found)
                        continue;
                }

                dicProperty.Add(ep.Name, new InternalProperty(ep));
                if (CRMDynTraceSwitch.Sw.TraceVerbose)
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 FillDicProperties entity: {0}, Adding Property name: {1}, type: {2}",
                        dEntity.Name, ep.Name, ep), CRMDynTraceSwitch.Sw.Info);
            }
            if (CRMDynTraceSwitch.Sw.TraceVerbose)
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 FillDicProperties END entity: {0}, count: {1}.", 
                    dEntity.Name,dicProperty.Count), CRMDynTraceSwitch.Sw.Info);
        }

        public override InternalDynamicEntity ToDynamicEntity(DynEntity dn)
        {
            if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 ToDynamicEntity BEG SchemaName: {0}", dn.SchemaName),CRMDynTraceSwitch.Sw.Info);
            return new InternalDynamicEntity(ToDynamicEntityRaw(dn));
        }
        public DynamicEntity ToDynamicEntityRaw(DynEntity dn)
        {
            if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 ToDynamicEntityRaw BEG SchemaName: {0}", dn.SchemaName),CRMDynTraceSwitch.Sw.Info);
            // Create the DynamicEntity object.
            DynamicEntity dEntity = new DynamicEntity();
            // Set the name of the entity type.
            dEntity.Name          = dn.SchemaName;
            // Set the properties of the contact.
            if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 ToDynamicEntityRaw properties count: {0} ", dn.dicProperty.Count),CRMDynTraceSwitch.Sw.Info);

            dEntity.Properties  = new Property[dn.Count];
            int                 i = 0;
            foreach (string s in dn.Keys)
            {
                if (s != null && dn.dicProperty.ContainsKey(s))
                {
                    if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 ToDynamicEntityRaw [{0}] elements = [{1}]->[{2}]",
                            i, s,GetPropertyValue(dn.dicProperty[s])),CRMDynTraceSwitch.Sw.Info);
                    dEntity.Properties[i++] = (Property)dn.dicProperty[s].Content;
                }
            }
            return dEntity;
        }

        public override string GetEntityName(InternalDynamicEntity dEntity)
        {
            return ((DynamicEntity)dEntity.Content).Name;
        }

        public override Guid CreateFromDynEntity(DynEntity dynEnt,bool isAdmin)
        {
            if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 CreateFromDynEntity SchemaName: {0}, isAdmin: {1}", dynEnt.SchemaName,isAdmin),CRMDynTraceSwitch.Sw.Info);
            // Create the DynamicEntity object.
            DynamicEntity dEntity       =   new DynamicEntity();
            EntityConfig Tconfig        =    new EntityConfig(this,dynEnt.SchemaName);

            // Set the name of the entity type.
            dEntity.Name            = dynEnt.SchemaName;

            // Set the properties of the contact.
            List<Property> Lst              =   new List<Property>();
            foreach (KeyValuePair<string, InternalProperty> kvp in dynEnt.dicProperty)
            {
                Property p              =    (Property)kvp.Value.Content;
                if (  ( p.Name != CrmStr.calendarrules ) && !Util3.ExtractAttributeFieldAsBool(Tconfig[p.Name], InternalAttributeFields.ValidForCreate))
                {
                    if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 CreateFromDynEntity Property Not valid for create Name: {0}", p.Name),CRMDynTraceSwitch.Sw.Info);
                    continue;
                }
                Lst.Add(p);
                if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 CreateFromDynEntity adding key: {0}, value: {1}", kvp.Key,GetPropertyValueRaw(p)),CRMDynTraceSwitch.Sw.Info);
            }
            dEntity.Properties              =   new Property[Lst.Count];
            int i                           =   0;
            foreach(Property p in Lst)
                dEntity.Properties[i++]     =   p;

            // Create the target.
            TargetCreateDynamic targetCreate    = new TargetCreateDynamic();
            targetCreate.Entity                 = dEntity;
            // Create the request object.
            CreateRequest create                = new CreateRequest();

            // Set the properties of the request object.
            create.Target                       = targetCreate;
            CreateResponse created              =   null;
            try
            {
                // Execute the request
                if (isAdmin)
                    created = (CreateResponse)adminExecuteRaw(create);
                else
                    created = (CreateResponse)userExecuteRaw(create);
            }
            catch(Exception ex)
            {
                if ( CRMDynTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 CreateFromDynEntity SchemaName: {0}, ex: {1}", dynEnt.SchemaName,ex),CRMDynTraceSwitch.Sw.Info);
                throw;
            }
            dynEnt.EntityID = created.id;
            if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 CreateFromDynEntity created SchemaName: {0}, id: {1}", dynEnt.SchemaName, dynEnt.EntityID),CRMDynTraceSwitch.Sw.Info);
            return dynEnt.EntityID;
        }

        public override InternalActivityParty CreateActivityParty(ADNDynActivityParty edyn)
        {
            return new InternalActivityParty(CreateActivityPartyRaw(edyn));
        }
        
        public activityparty CreateActivityPartyRaw(ADNDynActivityParty edyn)
        {
                activityparty ap        =   new activityparty();
                ap.partyid              =   CrmTypes.CreateLookup(edyn.partyType, edyn.partyid);
                if (edyn.ContainsKey(CrmStr.scheduledend))
                    ap.scheduledend     =   CrmTypes.CreateCrmDateTime(edyn.scheduledend);
                if (edyn.ContainsKey(CrmStr.scheduledstart))
                    ap.scheduledstart   =   CrmTypes.CreateCrmDateTime(edyn.scheduledstart);
                if (edyn.ContainsKey(CrmStr.participationtypemask))
                    ap.participationtypemask = CrmTypes.CreatePicklist(edyn.participationtypemask);
                ap.addressused          =   edyn.addressused;
                if (edyn.ContainsKey(CrmStr.donotemail))
                    ap.donotemail       =   CrmTypes.CreateCrmBoolean(edyn.donotemail);
                if (edyn.ContainsKey(CrmStr.donotfax))
                    ap.donotfax         =   CrmTypes.CreateCrmBoolean(edyn.donotfax);
                if (edyn.ContainsKey(CrmStr.effort))
                    ap.effort           =   CrmTypes.CreateCrmFloat(edyn.effort);
                if (edyn.ContainsKey(CrmStr.resourcespecid))
                    ap.resourcespecid   =   CrmTypes.CreateLookup(CrmStr.resourcespec, edyn.resourcespecid);
                return ap;
            }

        /// <summary>
        /// Update a dynamic entity
        /// </summary>
        public override void UpdateFromDynEntity(DynEntity dynEnt,bool isAdmin)
        {
            if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 UpdateFromDynEntity SchemaName: {0}, isAdmin: {1}", dynEnt.SchemaName,isAdmin),CRMDynTraceSwitch.Sw.Info);
/*            TargetRetrieveDynamic targetRetrieve    =   new TargetRetrieveDynamic();
            targetRetrieve.EntityName               =   dynEnt.SchemaName;
            targetRetrieve.EntityId                 =   dynEnt.EntityID;
            RetrieveRequest retrieve                =   new RetrieveRequest();
            retrieve.Target                         =   targetRetrieve;
            ColumnSet cols                          =   new ColumnSet();
            string PrimaryKeyName                   =   dynEnt.PrimaryKeyName;
            cols.Attributes                         =   new string[]{PrimaryKeyName,dynEnt.PrimaryFieldName};
            retrieve.ColumnSet                      =   cols;
            // Indicate that the BusinessEntity should be retrieved as a DynamicEntity.
            retrieve.ReturnDynamicEntities          =   true;
            // Execute the request.
            RetrieveResponse retrieved              =   null;
            try
            {
                if (isAdmin)
                    retrieved = (RetrieveResponse)adminExecuteRaw(retrieve);
                else
                    retrieved = (RetrieveResponse)userExecuteRaw(retrieve);
            }
            catch (Exception ex)
            {
                if ( CRMDynTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 UpdateFromDynEntity Retrieve Guid : {0}, ex: {1}", dynEnt.EntityID, ex),CRMDynTraceSwitch.Sw.Info);
                throw;
            }
            // Extract the DynamicEntity from the request.
            DynamicEntity dEntity           =   (DynamicEntity)retrieved.BusinessEntity;
*/  
            Guid CrmId                      =   dynEnt.PrimaryKeyGuidValue;
            // in case not here try to find it in EntityID-> if somebody just created a dynEntity with Ctor for create
            if (dynEnt.EntityID != Guid.Empty)
            {
                dynEnt.PrimaryKeyGuidValue =    dynEnt.EntityID;
                CrmId                      =    dynEnt.PrimaryKeyGuidValue;
            }
            if (CrmId == Guid.Empty)
            {
                string msg  =   string.Format("[V]CRMWrapper3 UpdateFromDynEntity No PrimaryKey Name: {0}", dynEnt.SchemaName);
                if ( CRMDynTraceSwitch.Sw.TraceError )
                        Trace.WriteLine( msg,CRMDynTraceSwitch.Sw.Info);
                throw new Exception(msg);
            }

            DynamicEntity dEntity           =   new DynamicEntity();
            // Set the name of the entity type.
            dEntity.Name                    =   dynEnt.SchemaName;
 
            EntityConfig Tconfig            =    new EntityConfig(this,dynEnt.SchemaName);

            // Set the name of the entity type.
            dEntity.Name            = dynEnt.SchemaName;

            List<Property> Lst              =   new List<Property>();
            // Set the properties of the contact.
            foreach (KeyValuePair<string, InternalProperty> kvp in dynEnt.dicProperty)
            {
                Property    p               =   (Property)kvp.Value.Content;
                if (!Tconfig.attributesDic.ContainsKey(p.Name))
                {
                    if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 UpdateFromDynEntity Property not in V3 Name: {0}", p.Name),CRMDynTraceSwitch.Sw.Info);
                    continue;
                }
                if ( !p.Name.Equals(dynEnt.PrimaryKeyName) &&
                        !Util3.ExtractAttributeFieldAsBool(Tconfig[p.Name], InternalAttributeFields.ValidForUpdate))
                {
                    if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                        Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 UpdateFromDynEntity Property Not valid for update Name: {0}", p.Name),CRMDynTraceSwitch.Sw.Info);
                    continue;
                }
                Lst.Add(p);
                if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 UpdateFromDynEntity adding key: {0}, value: {1}", kvp.Key, p),CRMDynTraceSwitch.Sw.Info);
            }

            dEntity.Properties              =   new Property[Lst.Count];
            int i                           =   0;
            foreach(Property p in Lst)
                dEntity.Properties[i++]     =   p;
            // Create the target.
            TargetUpdateDynamic target      =   new TargetUpdateDynamic();
            target.Entity                   =   dEntity;
            // Create the request object.
            UpdateRequest upd               =   new UpdateRequest ();

            // Set the properties of the request object.
            upd.Target                      =   target;

            // Execute the request
            UpdateResponse  updated         =   null;
            try
            {
            if (isAdmin)
                updated                     = (UpdateResponse)adminExecuteRaw(upd);
            else
                updated                     = (UpdateResponse)userExecuteRaw(upd);
            }
            catch(Exception ex)
            {
                if ( CRMDynTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 UpdateFromDynEntity SchemaName: {0}, ex: {1}", dynEnt.SchemaName,ex),CRMDynTraceSwitch.Sw.Info);
                throw;
            }
            if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 UpdateFromDynEntity END updated SchemaName: {0}", dynEnt.SchemaName),CRMDynTraceSwitch.Sw.Info);
        }

        /// <summary>
        /// Delete a dynamic entity
        /// </summary>
        public override void DeleteFromDynEntity(DynEntity dynEnt,bool isAdmin)
        {
            if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 DeleteFromDynEntity BEG SchemaName: {0}, isAdmin: {1}", dynEnt.SchemaName,isAdmin),CRMDynTraceSwitch.Sw.Info);

            // Create the target.
            TargetDeleteDynamic target      =     new TargetDeleteDynamic();
            target.EntityId                 =     dynEnt.EntityID;
            target.EntityName               =     dynEnt.SchemaName;
            // Create the request object.
            DeleteRequest upd               =       new DeleteRequest();

            // Set the properties of the request object.
            upd.Target                      =   target;

            // Execute the request
            DeleteResponse  updated         =   null;
            try
            {
                if (isAdmin)
                    updated                 =   (DeleteResponse)adminExecuteRaw(upd);
                else
                    updated                 =   (DeleteResponse)userExecuteRaw(upd);
            }
            catch(Exception ex)
            {
                if ( CRMDynTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 DeleteFromDynEntity SchemaName: {0}, ex: {1}", dynEnt.SchemaName,ex),CRMDynTraceSwitch.Sw.Info);
                throw;
            }
            if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 DeleteFromDynEntity END deleted SchemaName: {0}", dynEnt.SchemaName),CRMDynTraceSwitch.Sw.Info);
        }

        public override bool RetrieveFromDynEntity(DynEntity dynEnt,bool isAdmin)
        {
            if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 RetrieveFromDynEntity SchemaName: {0}, EntityID: {1}", dynEnt.SchemaName,dynEnt.EntityID),CRMDynTraceSwitch.Sw.Info);
            TargetRetrieveDynamic targetRetrieve    =   new TargetRetrieveDynamic();

            // Set the properties of the target.
            targetRetrieve.EntityName               =   dynEnt.SchemaName;
            if ( dynEnt.EntityID != Guid.Empty )
                    targetRetrieve.EntityId         =   dynEnt.EntityID;// fast
             else targetRetrieve.EntityId           =   dynEnt.PrimaryKeyGuidValue; //slow if real dynEntity

            // Create the request object.
            RetrieveRequest retrieve                =   new RetrieveRequest();

            // Set the properties of the request object.
            retrieve.Target                         =   targetRetrieve;
            retrieve.ColumnSet                      =   new AllColumns();

            // Indicate that the BusinessEntity should be retrieved as a DynamicEntity.
            retrieve.ReturnDynamicEntities          =   true;
            // Execute the request.
            RetrieveResponse retrieved              =   null;
            try
            {
                if (isAdmin)
                    retrieved                       =   (RetrieveResponse)adminExecuteRaw(retrieve);
                else
                    retrieved                       =   (RetrieveResponse)userExecuteRaw(retrieve);
            }
            catch (Exception ex)
            {
                if ( CRMDynTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 RetrieveFromDynEntity Guid : {0}, ex: {1}", dynEnt.EntityID, ex),CRMDynTraceSwitch.Sw.Info);
                return false;
            }
            dynEnt.dicProperty.Clear();
            // Extract the DynamicEntity from the request.
            DynamicEntity entity                    =   (DynamicEntity)retrieved.BusinessEntity;

            // Extract the fullname from the dynamic entity
            foreach (Property ep in entity.Properties)
            {
                dynEnt.dicProperty.Add(ep.Name, new InternalProperty(ep));
                if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 RetrieveFromDynEntity Adding Property name: {0}", ep.Name),CRMDynTraceSwitch.Sw.Info);
            }
            return true;
        }

        public override bool RetrieveFromDynEntity(DynEntity dynEnt,InternalColumnSet cols,bool isAdmin)
        {
            if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 RetrieveFromDynEntity SchemaName: {0}, EntityID: {1}, cols.length: {2}.",
                    dynEnt.SchemaName,dynEnt.EntityID, (cols == null ) ? 0:cols.Attributes.Length),CRMDynTraceSwitch.Sw.Info);
            TargetRetrieveDynamic targetRetrieve    =   new TargetRetrieveDynamic();

            // Set the properties of the target.
            targetRetrieve.EntityName               =   dynEnt.SchemaName;
            if ( dynEnt.EntityID != Guid.Empty )
                    targetRetrieve.EntityId         =   dynEnt.EntityID;// fast
             else targetRetrieve.EntityId           =   dynEnt.PrimaryKeyGuidValue; //slow if real dynEntity

            // Create the request object.
            RetrieveRequest retrieve                =   new RetrieveRequest();

            // Set the properties of the request object.
            retrieve.Target                         =   targetRetrieve;
            retrieve.ColumnSet                      =   (cols == null) ? (ColumnSetBase)(new AllColumns()):(ColumnSetBase)(ColumnSet)cols;

            // Indicate that the BusinessEntity should be retrieved as a DynamicEntity.
            retrieve.ReturnDynamicEntities          =   true;
            // Execute the request.
            RetrieveResponse retrieved              =   null;
            try
            {
                if (isAdmin)
                    retrieved                       =   (RetrieveResponse)adminExecuteRaw(retrieve);
                else
                    retrieved                       =   (RetrieveResponse)userExecuteRaw(retrieve);
            }
            catch (Exception ex)
            {
                if ( CRMDynTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 RetrieveFromDynEntity Guid: {0}, ex: {1}", dynEnt.EntityID, ex),CRMDynTraceSwitch.Sw.Info);
                return false;
            }
            
            dynEnt.dicProperty.Clear();
            
            // Extract the DynamicEntity from the request.
            DynamicEntity entity                    =   (DynamicEntity)retrieved.BusinessEntity;

            // Extract properties from the dynamic entity
            foreach (Property ep in entity.Properties)
            {
                dynEnt.dicProperty.Add(ep.Name, new InternalProperty(ep));
                if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 RetrieveFromDynEntity Adding Property name: {0}", ep.Name),CRMDynTraceSwitch.Sw.Info);
            }
            if ( CRMDynTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( "[V]CRMWrapper3 RetrieveFromDynEntity END.",CRMDynTraceSwitch.Sw.Info);
            return true;
        }

        public override void AssignFromDynEntity(DynEntity dynEnt,Guid wUserId, bool isAdmin)
        {
            SecurityPrincipal assignee  =   new SecurityPrincipal();
            // Set the properties of the SecurityPrincipal object.'
            // PrincipalId is a GUID that identifies the user or team 
            // that will own this record.
            assignee.PrincipalId        =   wUserId;

            TargetOwnedDynamic target   =   new TargetOwnedDynamic();
            target.EntityName           =   dynEnt.SchemaName;
            target.EntityId             =   dynEnt.EntityID;

            // Create the request object.
            AssignRequest assign        =   new AssignRequest();

            // Set the properties of the request object.'
            assign.Assignee             =   assignee;
            assign.Target               =   target;

            // Execute the request.
            AssignResponse assignResponse = null;
            try
            {
                if (isAdmin)
                    assignResponse = (AssignResponse)adminExecute(new InternalRequest(assign)).Content;
                else
                    assignResponse = (AssignResponse)userExecute(new InternalRequest(assign)).Content;
            }
            catch (Exception ex)
            {
                if ( CRMDynTraceSwitch.Sw.TraceError )
                    Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 Assign EntityName: {0}, EntityID : {1},UserId : {2}, isAdmin: {3}, ex: {4}", 
                        new object[] { dynEnt.SchemaName, dynEnt.EntityID, userId, isAdmin, ex }),CRMDynTraceSwitch.Sw.Info);
                throw;
            }
        }
        
        #region CRM properties worker methods

        /// <summary>
        /// Helper method to add a string as a StringProperty: creates the property, initializes its key and content, add it tointernal dic.
        /// </summary>
        public override StringInternalProperty AddStringProperty(string key, string val,DicProperties dic)
        {
            StringProperty sprop = new StringProperty();
            StringInternalProperty reslt =   new StringInternalProperty (sprop);
            dic[key] = reslt;
            sprop.Name = key;
            sprop.Value = val;
            return reslt;
        }

        public override CrmBooleanInternalProperty AddBooleanProperty(string key, Boolean val,DicProperties dic)
        {
            CrmBooleanProperty test = new CrmBooleanProperty();
            CrmBooleanInternalProperty reslt =   new CrmBooleanInternalProperty (test);
            dic[key] = reslt;
            test.Name = key;
            test.Value = CrmTypes.CreateCrmBoolean(val);
            test.Value.Value = val;
            return reslt;
        }

        public override CrmDateTimeInternalProperty AddDateTimeProperty(String name, string value,DicProperties dic)
        {
            CrmDateTimeProperty result = new CrmDateTimeProperty();
            CrmDateTimeInternalProperty reslt    =   new CrmDateTimeInternalProperty (result);
            dic[name] = reslt;
            result.Name = name;
            result.Value = CrmTypes.CreateCrmDateTime(value);
            return reslt;
        }

        public override CrmDecimalInternalProperty AddDecimalProperty(String name, Decimal value,DicProperties dic)
        {
            CrmDecimalProperty result = new CrmDecimalProperty();
            CrmDecimalInternalProperty reslt =   new CrmDecimalInternalProperty (result);
            dic[name] = reslt;
            result.Name = name;
            result.Value = CrmTypes.CreateCrmDecimal(value);
            return reslt;
        }

        public override CrmFloatInternalProperty AddFloatProperty(String name, double value,DicProperties dic)
        {
            CrmFloatProperty result         =   new CrmFloatProperty();
            CrmFloatInternalProperty reslt  =   new CrmFloatInternalProperty (result);
            dic[name]                       =   reslt;
            result.Name                     =   name;
            result.Value                    =   CrmTypes.CreateCrmFloat(value);
            return reslt;
        }

        public override CrmFloatInternalProperty AddFloatProperty(String name, float value,DicProperties dic)
        {
            CrmFloatProperty result         =   new CrmFloatProperty();
            CrmFloatInternalProperty reslt  =   new CrmFloatInternalProperty (result);
            dic[name]                       =   reslt;
            result.Name                     =   name;
            result.Value                    =   CrmTypes.CreateCrmFloat(value);
            return reslt;
        }

        public override CrmMoneyInternalProperty AddMoneyProperty(String name, Decimal value,DicProperties dic)
        {
            CrmMoneyProperty result         =   new CrmMoneyProperty();
            CrmMoneyInternalProperty reslt  =   new CrmMoneyInternalProperty (result);
            dic[name]                       =   reslt;
            result.Name                     =   name;
            result.Value                    =   CrmTypes.CreateCrmMoney(value);
            return reslt;
        }

        public override CrmNumberInternalProperty AddNumberProperty(String name, int value,DicProperties dic)
        {
            CrmNumberProperty result        =   new CrmNumberProperty();
            CrmNumberInternalProperty reslt =   new CrmNumberInternalProperty (result);
            dic[name]                       =   reslt;
            result.Name                     =   name;
            result.Value                    =   CrmTypes.CreateCrmNumber(value);
            return reslt;
        }

        public override CustomerInternalProperty AddCustomerProperty(string name, string type, Guid value,DicProperties dic)
        {
            CustomerProperty result         =   new CustomerProperty();
            CustomerInternalProperty reslt  =   new CustomerInternalProperty (result);
            dic[name]                       =   reslt;
            result.Name                     =   name;
            result.Value                    =   CrmTypes.CreateCustomer(type, value);
            return reslt;
        }

        public override DynamicEntityArrayInternalProperty AddDynamicEntityArrayProperty(String name, InternalDynamicEntityArray value,DicProperties dic)
        {
            DynamicEntityArrayProperty result           =   new DynamicEntityArrayProperty();
            DynamicEntityArrayInternalProperty reslt    =   new DynamicEntityArrayInternalProperty (result);
            dic[name]                                   =   reslt;
            result.Name                                 =   name;
            result.Value                                =   (DynamicEntity[])value.Content;
            return reslt;
        }

        public override EntityNameReferenceInternalProperty AddEntityNameReferenceProperty(String name, string value,DicProperties dic)
        {
            EntityNameReferenceProperty result          =   new EntityNameReferenceProperty();
            EntityNameReferenceInternalProperty reslt   =   new EntityNameReferenceInternalProperty (result);
            dic[name]                                   =   reslt;
            result.Name                                 =   name;
            result.Value                                =   CrmTypes.CreateEntityNameReference(value);
            return reslt;
        }

        public override KeyInternalProperty AddKeyProperty(String name, Guid value,DicProperties dic)
        {
            KeyProperty result          =   new KeyProperty();
            KeyInternalProperty reslt   =   new KeyInternalProperty (result);
            dic[name]                   =   reslt;
            result.Name                 =   name;
            result.Value                =   CrmTypes.CreateKey(value);
            return reslt;
        }

        public override LookupInternalProperty AddLookupProperty(String name, String type, Guid value,DicProperties dic)
        {
            LookupProperty result           =   new LookupProperty();
            LookupInternalProperty reslt    =   new LookupInternalProperty (result);
            dic[name]                       =   reslt;
            result.Name                     =   name;
            result.Value                    =   CrmTypes.CreateLookup(type, value);
            return reslt;
        }

        public override CalendarRulesInternalProperty AddCalendarRulesProperty(string name,object value,DicProperties dic)
        {
            CalendarRulesInternalProperty reslt =   new CalendarRulesInternalProperty(value);
            dic[name]                           =   reslt;
            return reslt;
        }

        public override OwnerInternalProperty AddOwnerProperty(String name, String type, Guid value,DicProperties dic)
        {
            OwnerProperty result = new OwnerProperty();
            OwnerInternalProperty reslt =   new OwnerInternalProperty (result);
            dic[name]                   =   reslt;
            result.Name                 =   name;
            result.Value                =   CrmTypes.CreateOwner(type, value);
            return reslt;
        }

        public override PicklistInternalProperty AddPicklistProperty(String name, int value,DicProperties dic)
        {
            PicklistProperty result         =   new PicklistProperty();
            PicklistInternalProperty reslt  =   new PicklistInternalProperty (result);
            dic[name]                       =   reslt;
            result.Name                     =   name;
            result.Value                    =   CrmTypes.CreatePicklist(value);
            return reslt;
        }

        public override StateInternalProperty AddStateProperty(String name, String value,DicProperties dic)
        {
            StateProperty result        =   new StateProperty();
            StateInternalProperty reslt =   new StateInternalProperty (result);
            dic[name]                   =   reslt;
            result.Name                 =   name;
            result.Value                =   value;
            return reslt;
        }

        public override StatusInternalProperty AddStatusProperty(String name, int value,DicProperties dic)
        {
            StatusProperty result           =   new StatusProperty();
            StatusInternalProperty reslt    =   new StatusInternalProperty (result);
            dic[name]                       =   reslt;
            result.Name                     =   name;
            result.Value                    =   CrmTypes.CreateStatus(value);
            return reslt;
        }

        public override UniqueIdentifierInternalProperty AddUniqueIdentifierProperty(String name, Guid value,DicProperties dic)
        {
            UniqueIdentifierProperty result         =   new UniqueIdentifierProperty();
            UniqueIdentifierInternalProperty reslt  =   new UniqueIdentifierInternalProperty (result);
            dic[name]                               =   reslt;
            result.Name                             =   name;
            result.Value                            =   CrmTypes.CreateUniqueIdentifier(value);
            return reslt;
        }

        #endregion CRM properties worker methods

        #region Extracting values

        /// <summary>
        /// beware that when a string value is string.empty, CRM server web services doesn't return the corresponding property
        /// This is a bad conception and to live with this, we must return string.Empywhen the value is not found.
        /// This could also mean that the attribut is not present....
        /// </summary>
        public override string StringPropertyValue(string key,DicProperties dic)
        {
            if ( dic.ContainsKey(key) )
                return ((StringProperty)dic[key].Content).Value;
            return string.Empty;
        }

        public override bool IsBooleanPropertyValueNull(string key,DicProperties dic)
        {
            return ((CrmBooleanProperty )dic[key].Content).Value.IsNull;
        }
        public override bool BooleanPropertyValue(string key,DicProperties dic)
        {
            return ((CrmBooleanProperty )dic[key].Content).Value.Value;
        }

        public override string DateTimePropertyValue(string key,DicProperties dic)
        {
            return ((CrmDateTimeProperty)dic[key].Content).Value.Value;
        }
        
        public override DateTime DateTimePropertyDate(string key,DicProperties dic,bool toUserTime)
        {
            CrmDateTimeProperty p = (CrmDateTimeProperty)dic[key].Content;
            if (p != null )
                return CRMUtil.ConvertDateFromCrm(((CrmDateTimeProperty)p).Value.Value,toUserTime);
            return CRMUtil.minDateTime;
        }

        public override bool IsDecimalPropertyValueNull(string key,DicProperties dic)
        {
            return ((CrmDecimalProperty)dic[key].Content).Value.IsNull;
        }
        public override decimal DecimalPropertyValue(string key,DicProperties dic)
        {
            return ((CrmDecimalProperty)dic[key].Content).Value.Value;
        }

        public override bool IsFloatPropertyValueNull(string key,DicProperties dic)
        {
            return ((CrmFloatProperty )dic[key].Content).Value.IsNull;
        }
        [Obsolete("Use DoublePropertyValue")]
        public override float FloatPropertyValue(string key,DicProperties dic)
        {
            return ((CrmFloatProperty )dic[key].Content).Value.Value;
        }
        
        public override double DoublePropertyValue(string key,DicProperties dic)
        {
            return (double)((CrmFloatProperty )dic[key].Content).Value.Value;
        }
        
        public override bool IsMoneyPropertyValueNull(string key,DicProperties dic)
        {
            return ((CrmMoneyProperty )dic[key].Content).Value.IsNull;
        }
        public override decimal MoneyPropertyValue(string key,DicProperties dic)
        {
            return ((CrmMoneyProperty )dic[key].Content).Value.Value;
        }

        public override bool IsNumberPropertyValueNull(string key,DicProperties dic)
        {
            return ((CrmNumberProperty)dic[key].Content).Value.IsNull;
        }
        public override int NumberPropertyValue(string key,DicProperties dic)
        {
            return ((CrmNumberProperty)dic[key].Content).Value.Value;
        }
        public override bool IsUniqueIdentifierPropertyValueNull(string key,DicProperties dic)
        {
            return ((UniqueIdentifierProperty)dic[key].Content).Value.IsNull;
        }
        public override Guid UniqueIdentifierPropertyValue(string key,DicProperties dic)
        {
            return ((UniqueIdentifierProperty)dic[key].Content).Value.Value;
        }
        public override bool IsPicklistPropertyIntValueNull(string key,DicProperties dic)
        {
            return ((PicklistProperty)dic[key].Content).Value.IsNull;
        }
        public override int PicklistPropertyIntValue(string key,DicProperties dic)
        {
            return ((PicklistProperty)dic[key].Content).Value.Value;
        }
        public override string PicklistPropertyNameValue(string key,DicProperties dic)
        {
            return ((PicklistProperty)dic[key].Content).Name;
        }
        
        public override string EntityNameReferencePropertyValue(string key,DicProperties dic)
        {
            return ((EntityNameReferenceProperty)dic[key].Content).Value.Value;
        }
                
        public override Guid KeyPropertyValue(string key,DicProperties dic)
        {
            if ( dic[key].Content is KeyProperty ) 
                return ((KeyProperty)dic[key].Content).Value.Value;
            if ( dic[key].Content is LookupProperty ) 
                return ((LookupProperty)dic[key].Content).Value.Value;
            return Guid.Empty;
        }

        public override bool  IsLookupPropertyValueNull(string key,DicProperties dic)
        {
            return ((LookupProperty )dic[key].Content).Value.IsNull;
        }
        public override string LookupPropertyType(string key,DicProperties dic)
        {
            return ((LookupProperty )dic[key].Content).Value.type;
        }
        public override string LookupPropertyName(string key,DicProperties dic)
        {
            return ((LookupProperty )dic[key].Content).Value.name;
        }
        
        public override Guid LookupPropertyValue(string key,DicProperties dic)
        {
            return ((LookupProperty )dic[key].Content).Value.Value;
        }

        public override object CalendarRulesPropertyValue(string key,DicProperties dic)
        {
            return ((calendarrule[])dic[key].Content);
        }
        
        public override int CalendarRulesPropertyLength(string key,DicProperties dic)
        {
            return ((calendarrule[])dic[key].Content).Length;
        }
        
        public override object CalendarRulesPropertyAtIndex(string key,DicProperties dic,int idx)
        {
            calendarrule[] cr   =   (calendarrule[])dic[key].Content;
            if ( ( cr != null ) && (idx < cr.Length ) )
                return cr[idx];
            return null;
        }

        public override Guid CalendarRulesPropertyLookupAtIndex(string key,DicProperties dic,int idx)
        {
            calendarrule[] cr   =   (calendarrule[])dic[key].Content;
            if ( ( cr != null ) && (idx < cr.Length ) )
                return cr[idx].calendarruleid.Value;
            return Guid.Empty;
        }


        public override bool IsOwnerPropertyValueNull(string key,DicProperties dic)
        {
            return ((OwnerProperty )dic[key].Content).Value.IsNull;
        }
        public override Guid OwnerPropertyValue(string key,DicProperties dic)
        {
            return ((OwnerProperty )dic[key].Content).Value.Value;
        }
        public override string OwnerPropertyName(string key,DicProperties dic)
        {
            return ((OwnerProperty)dic[key].Content).Value.name;
        }
        public override string OwnerPropertyType(string key,DicProperties dic)
        {
            return ((OwnerProperty)dic[key].Content).Value.type;
        }
        public override bool IsCustomerPropertyValueNull(string key,DicProperties dic)
        {
            return ((CustomerProperty)dic[key].Content).Value.IsNull;
        }
        public override Guid CustomerPropertyValue(string key,DicProperties dic)
        {
            return ((CustomerProperty)dic[key].Content).Value.Value;
        }
        public override string CustomerPropertyName(string key,DicProperties dic)
        {
            return ((CustomerProperty)dic[key].Content).Value.name;
        }
        public override string CustomerPropertyType(string key,DicProperties dic)
        {
            return ((CustomerProperty)dic[key].Content).Value.type;
        }
        public override InternalDynamicEntityArray DynamicEntityArrayProperty(String key,DicProperties dic)
        {
            if ( dic.ContainsKey(key) )
                return new InternalDynamicEntityArray(((DynamicEntityArrayProperty)dic[key].Content).Value);
            return null;
        }
        public override string StatePropertyValue(string key,DicProperties dic)
        {
            return ((StateProperty)dic[key].Content).Value;
        }

        public override string IncidentStatePropertyValue(string key,DicProperties dic)
        {
            return ((StateProperty)dic[key].Content).Value;
        }

        public override string StatePropertyNameValue(string key,DicProperties dic)
        {
            return ((StateProperty)dic[key].Content).Name;
        }
        public override int StatusPropertyIntValue(string key,DicProperties dic)
        {
            return ((StatusProperty)dic[key].Content).Value.Value;
        }
        public override string StatusPropertyNameValue(string key,DicProperties dic)
        {
            return ((StatusProperty)dic[key].Content).Value.name;
        }

        #endregion Extracting values
        #endregion special for DynEntity

        #region used by EntityList
        public override List<string> GetEntityList()
        {
            List<string> entLst     =   new List<string>();
                entLst.Insert(0,"uomschedule");
                entLst.Insert(0,"uom");
                entLst.Insert(0,"territory");
                entLst.Insert(0,"team");
                entLst.Insert(0,"task");
                entLst.Insert(0,"systemuser");
                entLst.Insert(0,"subject");
                entLst.Insert(0,"site");
                entLst.Insert(0,"service");
                entLst.Insert(0,"salesorderdetail");
                entLst.Insert(0,"salesorder");
                entLst.Insert(0,"salesliterature");
                entLst.Insert(0,"role");
                entLst.Insert(0,"resource");
                entLst.Insert(0,"quotedetail");
                entLst.Insert(0,"quoteclose");
                entLst.Insert(0,"quote");
                entLst.Insert(0,"productpricelevel");
                entLst.Insert(0,"product");
                entLst.Insert(0,"pricelevel");
                entLst.Insert(0,"phonecall");
                entLst.Insert(0,"opportunity");
                entLst.Insert(0,"list");
                entLst.Insert(0,"letter");
                entLst.Insert(0,"lead");
                entLst.Insert(0,"kbarticle");
                entLst.Insert(0,"invoicedetail");
                entLst.Insert(0,"invoice");
                entLst.Insert(0,"incidentresolution");
                entLst.Insert(0,"incident");
                entLst.Insert(0,"fax");
                entLst.Insert(0,"equipment");
                entLst.Insert(0,"email");
                entLst.Insert(0,"discount");
                entLst.Insert(0,"customeraddress");
                entLst.Insert(0,"contracttemplate");
                entLst.Insert(0,"contractdetail");
                entLst.Insert(0,"contract");
                entLst.Insert(0,"contact");
                entLst.Insert(0,"competitor");
                entLst.Insert(0,"campaignresponse");
                entLst.Insert(0,"campaign");
                entLst.Insert(0,"businessunit");
                entLst.Insert(0,"appointment");
                entLst.Insert(0,"account");
            return entLst;
        }
        #endregion used by EntityList

        #region Serialize into XML and return the string
        
        public override string Serialize(DynEntity dyn)
        {
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 Serialize BEG dyn.schemaname: {0}", dyn.SchemaName),CRMTraceSwitch.Sw.Info);
            string xml                              =   string.Empty;
            try
            {
                StringBuilder sb                    =   new StringBuilder();
                DynamicEntity dEnt                  =   ToDynamicEntityRaw(dyn);
                
                XmlSerializer serializer = new XmlSerializer(typeof(DynamicEntity));

                // The using statement also closes the StreamWriter.
                using (StringWriter writer          =   new StringWriter(sb)) 
                {
                   serializer.Serialize(writer,dEnt);
                }
                xml                                 =   sb.ToString();
            }
            catch(Exception ex) // not throwing in Ctor
            {
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 Deserialize<T> ex: {0}",ex),CRMTraceSwitch.Sw.Info);
                throw;
            }
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 Serialize BEG dyn.schemaname: {0}", dyn.SchemaName),CRMTraceSwitch.Sw.Info);
            return xml;
        }

        #endregion

        #region Deserialize the CRM contact from XML

        public override T Deserialize<T>(ResetWrapperHandler fnr, string xml)
        {
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 Deserialize<T> BEG xml: {0}", xml),CRMTraceSwitch.Sw.Info);
            T dyn                             =   null;
            try
            {
                DynamicEntity dEnt          =   new DynamicEntity();
                XmlSerializer serializer    =   new XmlSerializer(typeof(DynamicEntity));
                using ( StringReader reader =   new StringReader(xml) )
                {
                    // Deserialize the contact object.
                    object tmp              =   serializer.Deserialize(reader);
                    dEnt                    =   tmp as DynamicEntity;
                }
                dyn                         =   new T();
                dyn.InitTemplate(fnr,new InternalDynamicEntity(dEnt),null,null);
                dyn.EntityID                =   dyn.PrimaryKeyGuidValue;
            }
            catch(Exception ex) 
            {
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 Deserialize<T> ex: {0}",ex),CRMTraceSwitch.Sw.Info);
                throw;
            }
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 Deserialize<T> END SchemaName: {0}",dyn.SchemaName),CRMTraceSwitch.Sw.Info);
            return dyn;
        }

        #endregion Deserialize the CRM contact from XML

        #region InitializeFrom
        
        public override Guid InitializeFrom(DynEntity dyn,string targetEntity,bool isAdmin)
        {
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 InitializeFrom BEG SchemaName: {0}, targetEntity: {1}",dyn.SchemaName,targetEntity),CRMTraceSwitch.Sw.Info);
            Guid createdId              =   Guid.Empty;
            try
            {
                InitializeFromRequest req   =   new InitializeFromRequest();
                req.ReturnDynamicEntities   =   true;
                req.TargetEntityName        =   targetEntity;
                req.TargetFieldType         =   CRM3Server.TargetFieldType.ValidForCreate;
                req.EntityMoniker           =   new Moniker();
                req.EntityMoniker.Id        =   dyn.PrimaryKeyGuidValue;
                req.EntityMoniker.Name      =   dyn.SchemaName;

                InitializeFromResponse resp = null;
                if (isAdmin)
                        resp                =   (InitializeFromResponse) adminService3.ExecuteRaw(req);
                else    resp                =   (InitializeFromResponse) userService3.ExecuteRaw(req);
                if (isAdmin)
                        createdId           =   adminService3.CreateRaw(resp.Entity);
                else    createdId           =   userService3.CreateRaw(resp.Entity);
            }
            catch (SoapException sx)
            {
                string msg  =   string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 InitializeFrom ex: {0}-{1}", sx, sx.Detail.InnerText);
                if ( CRMTraceSwitch.Sw.TraceError )
                    Trace.WriteLine(msg ,CRMTraceSwitch.Sw.Info);
                throw new CRMWrapperException(msg, sx);
            }
            catch(Exception ex)
            {
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[E]CRMWrapper3 InitializeFrom ex: {0}",ex),CRMTraceSwitch.Sw.Info);
                throw;
            }
            if ( CRMTraceSwitch.Sw.TraceVerbose )
                Trace.WriteLine( string.Format(CultureInfo.InvariantCulture,"[V]CRMWrapper3 InitializeFrom END createdId: {0}",createdId),CRMTraceSwitch.Sw.Info);
            return createdId;
        }
        
        #endregion InitializeFrom
    }
}
